http://blog.csdn.net/jia635/article/details/39256187
以前听同时说反射很强大,看了一些相关文章今天把反射总结一下。
说明:反射主要用于开发框架,即制作框架;
一、获得class对象
class<?> c = class.forname("classname"); 抛出classnotfoundexception
二、获得实现接口
class<?> inters[] = c.getinterfaces();
for(int i=0;i<inters.length;i++){
system.out.print(inters[i].getname()+" "); //getname()方法为取得接口名称;
}
三、获得父类
class<?> superclass = c.getsuperclass(); //获得父类
string name = superclass.getname(); //获得父类名称
四、取得构造方法
constructor cons[] = c.getconstructors(); //获得公开的构造方法
constructor dcons[] = c.getdeclaredconstructors(); //获得全部构造方法
string modifier = modifier.tostring(cons[i].getmodifiers()); //获得访问权限
string name = cons[i].getname(); //获得构造方法名称
class<?> params[] = cons[i].getparametertypes(); //获得参数类型对象
五、获得method
method ms[] = c.getmethods(); //返回公共的全部方法,包括继承方法
method dms[] = c.getdeclaredmethods(); //返回本类全部方法,不包括继承的方法
class<?> rt = ms[i].getreturntype();
class<?>params[] = ms[i].getparametertypes();
string name = ms[i].getname();
string modifier = modifier.tostring(ms[i].getmodifiers());
class<?>ex[] = ms[i].getexceptiontypes(); //获得异常
string name = ex[i].getname(); //获得异常名称
六、获得field
field fs[] = c.getfields(); //获得公共属性,包括继承属性
field dfs[] = c.getdeclaredfields(); // 获得本类全部属性
class<?> type = fs[i].gettype(); //获得属性的类型对象
string name = fs[i].getname(); //获得属性的名称
string modifier = modifier.tostring(fs[i].getmodifiers());
七、通过反射创建一个对象
(1)
class<?> c = class.forname("person");
person p = (person)c.newinstance();
(2)
constructor con = c1.getconstructor(class....param);
object obj = con.newinstance(object obj); //根据构造函数创建一个实例
八、constructor创建对象
class c = class.forname("person");
constructor<?> cons[] = c.getconstructors();
person p = (person)cons[0].newinstance("xiazdong",15);
注:如果调用的构造函数为私有,则需要c.setaccessible(true);
九、调用特定方法
method m = c1.getmethod("funcname",class<?>...c); //funcname表示调用方法的名称,c表示参数的class对象
例如:method m = c1.getmethod("fun",string.class,int.class); 表示调用fun(string,int);函数
object obj = m.invoke(c1.newinstance(),"xiazdong",20); //如果有返回值,则invoke函数返回;
注:如果是调用静态的方法,则不需要设置对象;
object obj = m.invoke(null,"xiazdong");
注:如果参数中有数组,比如 public static void main(string[]args);
则
method m = c1.getmethod("main",string[].class);
m.invoke(null,(object)new string[]{"aa","bb"});是对的;
m.invoke(null,new string[]{"aa","bb"}); 会调用 main(string,string);函数;
十、调用特定属性
field f = c1.getdeclaredfield("name"); //返回name属性
f.setaccessible(true); //私有属性可见
string name = (string)f.get(object obj); //返回obj对象的name属性的值
f.set(object obj,string n); //设置obj对象的name属性为n值;
十一、操作数组
int tmp[] = {1,2,3};
class<?> c = tmp.getclass().getcomponenttype();
array.getlength(tmp); //tmp数组的长度
c.getname(); //获得数组类型名称
array.get(object obj,int index); //获得obj数组的index索引的数值
array.set(object obj,int index,value); //设置obj数组的index索引的数值为value;
object obj = array.newinstance(c,length); //c为数组的类型,length为数组的长度;obj为返回的数组对象;
示例:
[java]
view plaincopyprint?
import java.lang.reflect.*;
public class getmethoddemo01{
public static void main(string args[])throws exception{
class<?> c1 = class.forname("person");
method m = c1.getmethod("sayhello");
m.invoke(c1.newinstance());
method m2 = c1.getmethod("sayhello2",string.class,int.class);
string str = (string)m2.invoke(c1.newinstance(),"xiazdong",123);
system.out.println(str);
field namefield = c1.getdeclaredfield("name");
field agefield = c1.getdeclaredfield("age");
namefield.setaccessible(true);
agefield.setaccessible(true);
person obj = (person)c1.newinstance();
obj.setname("xzdong");
obj.setage(12);
system.out.println(namefield.get(obj));
system.out.println(agefield.get(obj));
method setname = c1.getmethod("setname",string.class);
setname.invoke(obj,"changed");
method getname = c1.getmethod("getname");
system.out.println(getname.invoke(obj));
int tmp[] = {1,2,3};
class<?> c3 = tmp.getclass().getcomponenttype();
system.out.println(c3.getname());
system.out.println("第一个数:"+array.get(tmp,0));
array.set(tmp,0,5);
object arr = array.newinstance(c3,5);
system.arraycopy(tmp,0,arr,0,array.getlength(tmp));
system.out.println(array.get(arr,2));
system.out.println(array.get(arr,3));
}
}
interface china{
public static final string name = "china";
public int age = 60;
public void sayhello();
public string sayhello2(string name,int age);
class person implements china{
private string name;
private int age;
public string getname(){
return name;
public void setname(string name){
this.name = name;
public int getage(){
return age;
public void setage(int age){
this.age = age;
public void sayhello(){
system.out.println(name+" "+age);
public string sayhello2(string name,int age){
return name+" "+age;
十一、工厂设计模式
1.最简单的工厂设计模式
场景:有一个fruit接口,apple类和orange类都实现了fruit接口,factory用来生产水果;
import java.io.*;
import java.util.*;
interface fruit{
public void eat();
class apple implements fruit{
public void eat(){
system.out.println("吃苹果");
class orange implements fruit{
system.out.println("吃橘子");
class factory{
public static fruit getinstance(string name)throws exception{
fruit f = null;
if("apple".equals(name)){
f = new apple();
}
else if("orange".equals(name)){
f = new orange();
if(f!=null){
return f;
else return null;
public class factorydemo01{
fruit f = factory.getinstance("apple");
f.eat();
2.通过反射实现
上面的例子有一个坏处,就是在factory的getinstance代码会随着水果数量增加而增加,比如如果增加了一个banana类,则需要添加
if(name.equals("banana")){...}
这样非常不方便,因此反射就是一个很好的解决方法:
fruit f = null
fruit f = (fruit)class.forname(name).newinstance();
3.增加灵活性:配置文件
但是还有一个缺点,就是如果apple类等有包名,则如果要访问此类,必须添加包名+类名称才可以。比如apple类的最上方:package org;则必须通过org.apple才可以访问apple类。因此通过properties文件可以解决这个问题;
private factory(){}
properties p = new properties();
p.load(new fileinputstream("1.properties"));
string str = p.getproperty("apple");
fruit f = factory.getinstance(str);
1.properties代码:
apple=apple
orange=orange