反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵Java代码的程序。能够分析类能力的程序成为反射(reflective)。反射机制的功能极其强大,可以用来:在运行中分析类的能力;在运行中查看对象;实现通用的数组操作代码;利用Method对象,这个对象很像C++中的函数指针。
在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。然而,可以通过专门的Java类访问这些信息。保存这些信息的类被称为Class。Object类中的getClass()方法将会返回一个Class类型的实例。
Class是java.lang包中的类,该类的实例可以帮助程序创建其他类的实例或者取得其他类的对象的内部信息。
使用Class实例化一个对象
创建对象最常用的方式就是使用new运算符和类的构造方法,实际上也可以使用Class对象得到某个类的实例。步骤如下:
- 使用Class的类方法得到一个和某类(参数className指定的类)相关的Class对象,public static Class forName(String className) throws ClassNotFoundException。上述方法返回一个和参数className指定的类相关的Class对象。如果类在某个包中,className必须带有包名,例如,className = “java.util.Data”。
- 步骤1中获得的Class对象调用public Object newInstance() throws InstantiationException, IllegalAccessException方法就可以得到一个className类的对象。
要特别注意的是:使用Class对象调用newInstance()实例化一个className类的对象时,className类必须有无参数的构造方法。
获取类的有关信息
当一个类被加载且创建对象时,和该类相关的一个类型为Class的对象就会自动创建,任何对象调用getClass()方法都可以获取和该对象相关的一个Class对象,这个Class对象调用如下的方法可以获取对象的有关信息,比如,创建该对象的类的名字、类中的方法名称、成员变量的名称等等。
1 import java.lang.reflect.*; 2 import java.util.Date; 3 4 public class Example { 5 public static void main(String[] args) { 6 Date date = new Date(); 7 Class cs = date.getClass(); 8 String className = cs.getName(); 9 Constructor[] con = cs.getDeclaredConstructors(); 10 Field[] field = cs.getDeclaredFields(); 11 Method[] method = cs.getDeclaredMethods(); 12 13 System.out.println("className:" + className); 14 System.out.println("class constructors:"); 15 for (Constructor c : con) { 16 System.out.println(c.toString()); 17 } 18 System.out.println("class fields:"); 19 for (Field f : field) { 20 System.out.println(f.toString()); 21 } 22 System.out.println("class methods:"); 23 for (Method m : method) { 24 System.out.println(m.toString()); 25 } 26 } 27 }
反射之实现通用的数组操作代码和利用Method暂时没有用到,暂且不写……