一、反射的理解
首先我们看看网友们对于反射的理解.
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、获取类、属性、方法的修饰域
类Class、Method、Constructor、Field都有一个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, "长尾巴");
}
}