Java程序中许多对象在运行时都会出现两种类型:编译期类型和运行期类型。例如:
Person p = new Student();
p编译期是Person类型,运行期是Student类型。如果我们需要调用该对象的运行期类型的某些方法,有两种方式:
在编译时和运行时完全知道对象和类的真实信息,这种情况下可以使用instanceof或isInstance()来进行判断;
如果编译时完全无法预知该对象和类的信息,就必须使用反射。
Class对象包含很多方法,通过这些方法可以完成以下功能(具体方法可以查阅API):
创建对象两种生成方式:
调用方法:
当获得某个类的Class对象后,就可以通过该Class对象的getMethods()方法或getMethod()方法来获取全部或指定的方法----这两个方法返回的是Method[]数组,或Method对象。
每个Method对象对应一个方法,获得Method对象后程序可以通过该Method对象来调用它对应的方法。在每个Method中包含一个以下方法:
Object invoke(Object obj, Object... args):该方法中第一个参数obj是执行该方法的主调,后面的args是执行该方法时要传入的实参。
当通过Method的invoke()方法来调用对应方法时,Java会要求程序必须有调用该方法的权限。如果确实要调用private方法,可以通过下面的方法取消Java语言的访问权限检查:
setAccessable(boolean flag):值为true,则指示该Method在使用时取消Java语言访问权限检查;
其实setAccessable()方法并不属于Method,而是属于他的父类AccessableObject,所以Method、Constructor、Field、都可以调用该方法。从而实现通过反射调用private方法、private构造器、private成员变量。
访问成员变量:
通过Class对象的getFields()或getFirld()可以获取该类所包括的全部成员变量或指定成员变量。这两个方法返回的是Field[]数组,或Field对象。
每个Field对象对应一个成员变量,获得Field对象后程序可以通过该Method对象来访问该成员变量。在每个Field中包含两个个以下方法:
这里的Xxx对应8中基本数据类型,如果是对象引用,则省略set/get后面的Xxx.
Array类可以表示所有的数组,Array配合反射机制可以动态地创建数组、操作数组元素等。