java中反射机制的学习

一、反射的理解

首先我们看看网友们对于反射的理解.

A:                                                                                                                                                          正常情况是java虚拟机根据你的类的定义,创建出一个对象。反射则是相反的过程,可以根据一个对象的引用,解析它的定义信息(属性,方法),进而可以操作它的属性,调   用它的方法,当然也可以创建出新的对象。---来自qwqwqw408
B:                                                                                                                                                          一句话来概括反射机制就是:动态地获取类的一切信息,并利用这些信息做一些你想做的事情---来自justinavril
第一 反射可以操作某个类的私有变量和方法
第二 反射操作对象更加灵活 如 struts的form  只要有了form对象和 property名字就可以利用反射给property赋值和取值 对这类操作 一个方法就可以搞定。---来自<span style="color: rgb(102, 102, 102); font-family: Helvetica, Tahoma, Arial, sans-serif;  line-height: 24px; background-color: rgb(245, 245, 245);"><strong>justinavril</strong></span>
C:                                                                                                                                                          如果hibernate不用字段进行反射映射 那么每个HQL的编译和结果处理 将无法进行。
第三 反射方式调用方法 动态代理 扩展API 。sping ioc,aop也都是用的反射
第四  运行过程中对未知类进行初始化等
我都是用反射在窃取和扩展一些收费的无法反编译的API---来自a276202460

没有错,他们说的都对就是对类的动态加载,你可以通过反射来操纵类中的一切,无论这个类中的变量和方法是不是private,我们都可以应用。

二、反射机制中需要使用到的类

我把需要使用的类列在下表中,其中对我们特别有用的类,通过着重标记显示出来,并将在后面的使用中逐步解释:

三、Class

  首先向大家说明一点,Class本身就是一个类,Class是该类的名称。看以下下面这个类的定义:

  public class MyButton extends Button {...}

   注意到上面的class的首字母是小写,它表示的是一种类类型,但是我们的Class是一个类,相当于上面定义的MyButton类。所以,千万不要把这里的Class做为一个类类型来理解。明白这一点,我们继续。

  Class类是整个Java反射机制的源头,Class类本身表示Java对象的类型,我们可通过一个Object对象的getClass()方法取得一个对象的类型,此函数返回的就是一个Class类。获取Class对象的方法有很多种:

boolean.class byte.class  int.class  long.class float.class double.class 

  在平时的使用,要注意对这几种方法的灵活运用,尤其是对Class.forName()方法的使用。因为在很多开发中,会直接通过类的名称取得Class类的对象。

四、获取类的相关信息

1、获取构造方法

  Class类提供了四个public方法,用于获取某个类的构造方法。

    Constructor getConstructor(Class[] params)     根据构造函数的参数,返回一个具体的具有public属性的构造函数

    Constructor getConstructors()     返回所有具有public属性的构造函数数组

    Constructor getDeclaredConstructor(Class[] params)     根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)

    Constructor getDeclaredConstructors()    返回该类中所有的构造函数数组(不分public和非public属性)

  由于Java语言是一种面向对象的语言,具有多态的性质,那么我们可以通过构造方法的参数列表的不同,来调用不同的构造方法去创建类的实例。同样,获取不同的构造方法的信息,也需要提供与之对应的参数类型信息;因此,就产生了以上四种不同的获取构造方法的方式。

2、获取类的成员方法

  与获取构造方法的方式相同,存在四种获取成员方法的方式。

    Method getMethod(String name, Class[] params)    根据方法名和参数,返回一个具体的具有public属性的方法

    Method[] getMethods()    返回所有具有public属性的方法数组

    Method getDeclaredMethod(String name, Class[] params)    根据方法名和参数,返回一个具体的方法(不分public和非public属性)

    Method[] getDeclaredMethods()    返回该类中的所有的方法数组(不分public和非public属性)

     在获取类的成员方法时,有一个地方值得大家注意,就是getMethods()方法和getDeclaredMethods()方法。

    getMethods():用于获取类的所有的public修饰域的成员方法,包括从父类继承的public方法和实现接口的public方法;

    getDeclaredMethods():用于获取在当前类中定义的所有的成员方法和实现的接口方法,不包括从父类继承的方法。

3、获取类的成员变量(成员属性)

  存在四种获取成员属性的方法

    Field getField(String name)    根据变量名,返回一个具体的具有public属性的成员变量

    Field[] getFields()    返回具有public属性的成员变量的数组

    Field getDeclaredField(String name)    根据变量名,返回一个成员变量(不分public和非public属性)

    Field[] getDelcaredField()    返回所有成员变量组成的数组(不分public和非public属性)

4、获取类、属性、方法的修饰域

  类ClassMethodConstructorField都有一个public方法int getModifiers()。该方法返回一个int类型的数,表示被修饰对象( Class、 Method、 Constructor、 Field )的修饰类型的组合值。

  在开发文档中,可以查阅到,Modifier类中定义了若干特定的修饰域,每个修饰域都是一个固定的int数值,列表如下:

    

五、如何调用类中的private方法

  

1、创建一个类的实例

  在得到一个类的Class对象之后,我们可以利用类Constructor去实例化该对象。Constructor支持泛型,也就是它本身应该是Constructor<T>

    

                       //获得无参数的构造函数
			Constructor constructor = animalClass03.getConstructor(null);
			//通过获得的无参数构造器可以 通过newInstance来实现一个对象;
			Object monkey01 = constructor.newInstance();

2、行为

  Method类中包含着类的成员方法的信息。在Method类中有一个public成员函数:Object invoke(Object receiver, Object... args),参数receiver指明了调用对象,参数args指明了该方法所需要接收的参数。由于我们是在运行时动态的调用类的方法,无法提前知道该类的参数类型和返回值类型,所以传入的参数的类型是Object,返回的类型也是Object。(因为Object类是所有其他类的父类)

  

/**获得类的方法并调用方法**///其实和变量没有太大的区别,区别是增加了参数而已
			Method[] methods = animalClass03.getDeclaredMethods();
			for(int i=0;i<methods.length;i++){
				if(methods[i].getName().equals("yaoWeiba")){
					methods[i].setAccessible(true);
					Object[] parameters = new Object[]{
							new String("小强"),true,3
					};
					methods[i].invoke(monkey03, parameters);
				}
			}

 3、属性

  对类的成员变量进行读写,在Field类中有两个public方法:

    Object get(Object object),该方法可用于获取某成员变量的值

    Void set(Object object, Object value),该方法设置某成员变量的值

  其中,Object参数是需要传入的对象;如果成员变量是静态属性,在object可传入null

//获得类中所有的变量,但是只有自己类中的变量,没有父类继承过来的变量
			Field[] fieldsAll = animalClass03.getDeclaredFields();
			for(int i=0;i<fieldsAll.length;i++){
				System.out.println(fieldsAll[i].getName());
				fieldsAll[i].setAccessible(true);//private 的变量通过这个设置后,我们也可以为其赋值了,不然不能访问
				//如果变量时String类型的,那么我们就为这个变量赋值,为monkey03这个对象中的tile赋值
				if(fieldsAll[0].getType()==String.class){
					fieldsAll[0].set(monkey03, "长尾巴");
				}
				
			}

六、运行demo

        

点击打开链接


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章