什么是反射?
反射就是把一个类中的各种元素映射成一个类。
得到一个类中的元素都是从这个类的字节码中得到的。
所以要得到反射的对象,必须先得到这个类的字节码。
得到字节码有三种方式:
1. 对象.getClass();
String str = "abc";
str.getClass();
2. 类.class ;
String.class ;
3. Class.forName();
Class.forName("java.lang.String") ;
构造方法的反射:
反射就是把一个类中的各种元素映射成一个类。构造方法是类中的一个元素,所以可以反射为一个类。
这个类是Constructor类。一个构造方法对应一个Constructor对象。
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
String str1 = (String) constructor1.newInstance(new StringBuffer("abc"));
通过构造方法对象创建一个String对象。由于编译时编译器并不知道该构造方法对象对应的类是哪个,所以要进行类型转换,告诉编译器通过改构造方法得到的是一个String类型的对象。
newInstance()方法:
使用此 Constructor
对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
newInstance()方法的参数是一个对象。
构造方法的反射得到的对象具有构造方法的特性,也就是创建对象并实例化。
成员变量的反射:
成员变量反射用到的类是Field;
自己写一个类来演示成员变量反射的用法。
Field fieldX = p1.getClass().getField("x");
fieldX不是对象的成员变量,而是类的成员变量。
如果要得到具体某一个对象的某个成员变量的值,则要把该对象作为参数传给fieldX的get()方法。
fieldX.get(p1) 。
getField()方法只能得到类中公有的成员,要得到私有成员,学要用到另一个方法:
getDeclaredField( )
该方法可以访问类中的private成员。
得到该成员之后,并不能直接拿来用,要先把该私有成员设置为可以使用,才可以拿来用,通过下面方法把得到的私有成员设置为可以用的:
fieldX.setAccessible(true);
Field类还提供了一个得到所有成员变量的方法:getFields()
通过下面程序演示。
Person类中有几个不同类型的成员变量,通过getFields()方法可以得到所有公有的成员变量。
通过getDeclaredFields()方法可以得到所有的私有成员变量。
通过上面的方法就可以实现成员变量的反射。
成员方法也是类中的成分,所以也可以进行反射。
成员方法的反射用到Method类;一个Method对象代表一个类中的一个方法。
由字节码对象调用getMethod()方法得到对应方法的反射对象。
Method method = 字节码对象.getMethod(方法名, 参数类型);
method.invoke(对象名, 给方法传递的参数);
对象名如果为空,表示该方法不能被对象调用,说明该方法是静态方法。
在Person类中写一个show()方法:
public void show(String str)
{
System.out.println(str);
}
得到该show()方法的反射对象,并使用反射对象执行该方法
对接受数组参数的方法进行反射:
要把一个数组作为一个参数传递。main()方法的参数就是数组类型的,以main()方法的反射为例来看看:
出现异常了!为什么会这样?
因为在传递数组作为参数时,数组被拆开了,没有被当做一个参数传递。所以要强调数组是一个参数。
每一个数组的父类都是Object数组。
所以使用下面方法可以把数组转换为一个参数。
通过上面的几个例子就可以看出,反射的概念和用法。
反射就是把一个类中的各种元素映射成一个类。
反射的实现就是由类的字节码对象得到类中成员变量或成员方法对应的对象。通过该对象的get()方法得到成员变量,或者通过方法对象的invoke()方法实现成员方法。