关于JAVA中的反射机制的总结


在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法,并能够实例化该类成对象,并调用其方法和成员。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

JAVA中的反射机制是一种能够大大增强程序扩展性的技术。当一个程序封装完成后(生成exe文件),如果想要对该程序进行功能扩展,不用进行代码的重新修改(也不可能拿到源码),只要修改配置文件(一般是XML)就可以完成扩展。

这样的程序为外部提供了一个接口,只要按照该接口的规则定义一个对象(功能),即可以为应用程序扩展该功能。

可以这样比喻,你买了一块电脑主板(封装好的程序),此时你想要添加一块声卡(要扩展的功能),此时只能够通过一个pci接口(应用程序提供的接口)来进行扩展。声卡的接口必须符合PCI的规则才可以被主板使用。通过添加驱动程序(修改XML配置文件)来进行扩展功能。

具体到代码实现分为以下几步:

1、定义一个接口(PCI)及一系列的方法用作加载功能。

2、定义一个对象并且实现该接口,复写其中的方法。

3、在配置文件中添加该对象的名称(全名,包括路径)键值对。

4、定义一个输入流,读入配置文件进properties集(健壮性判断);

5、使用for循环挨个获取properties集中的对象名称;

6、获取名称后用Class加载这个类,并实例化一个该对象(可以直接进行类型强转,因为已知是PCI接口)。

7、使用对象。

1         File configFile = new File("pci.properties");
 2         
 3         Properties prop = new Properties();
 4         FileInputStream fis = new FileInputStream(configFile);
 5         
 6         prop.load(fis);
 7         
 8         for(int x=0; x<prop.size(); x++){
 9             
10             String pciName = prop.getProperty("pci"+(x+1));
11             
12             Class clazz = Class.forName(pciName);//用Class去加载这个pci子类。 
13             
14             PCI p = (PCI)clazz.newInstance(); //PCI接口已经定义好了,有open和close两个方法
15             
16             mb.usePCI(p);//mb是主板对象,定义了一个使用PCI接口对方法
17         }
18         
19         fis.close();

 不仅如此,有时还需要或得该对象的有参数构造器,成员,成员方法

1、创建对象实例

//1、指定该类的名称
String className = "cn.itcast.bean.Person";
//2、通过Class类的forName()方法获取该类(从.class文件中获取)
Class clazz = Class.forName(className);
//3、通过Class对象的newInstance()方法创建对象,无参构造器
Object obj = clazz.newInstance();

问题:

1、从上面代码可以发现,如果要用有参构造器实例化对象的话就不行

2、实例化的对象时Object类,要想办法downcast

2、获取其任意构造器

String name = "cn.itcast.bean.Person";
//1、找寻该名称类文件,并加载进内存,并产生Class对象。
Class clazz = Class.forName(name);
//2、获取到了指定的构造函数对象,构造器也有自己的对象。getConstructor(,)的参数列表对应于所需构造器的参数列表的类对象
Constructor constructor = clazz.getConstructor(String.class,int.class);
        
//3、通过该构造器对象的newInstance方法进行对象的初始化。
Object obj = constructor.newInstance("小明",38);

3、获取其成员

Class clazz = Class.forName("cn.itcast.bean.Person");

Field field = null;

//clazz.getField("age");//只能获取公有的,

field = clazz.getDeclaredField("age");//只获取本类,但包含私有。 参数为成员名

//对私有字段的访问取消权限检查。暴力访问。
field.setAccessible(true);

Object obj = clazz.newInstance();

field.set(obj, 89);//将obj对象中的对应field成员值设为89


Object o = field.get(obj);//返回obj对象中的field成员的值

System.out.println(o);//89

4、获取方法(类似于构造器的获取)

public static void getMethodDemo_3() throws Exception {
        
    Class clazz = Class.forName("cn.itcast.bean.Person");
        
    Method method = clazz.getMethod("paramMethod", String.class,int.class);//第一个参数是方法名,考虑到重载,所以后面要加上参数列表来定位唯一的方法
        
    Object obj = clazz.newInstance();
        
    method.invoke(obj, "小强",89);//调用obj对象中的method方法,且传递了参数。
            
}
public static void getMethodDemo() throws Exception {
        
    Class clazz = Class.forName("cn.itcast.bean.Person");
        
    Method[] methods  = clazz.getMethods();//获取的都是公有的方法。 
    methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有。 返回一个方法数组,方法对象数组
    for(Method method : methods){
        System.out.println(method);
    }        
}

 

posted @ 2016-04-04 11:26  斯巴达之狐  阅读(222)  评论(0编辑  收藏  举报