帮助文档
TutorialsAPI另一篇不错的文章
概述
Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。例如,使用它能获得 Java 类中各成员的名称并显示出来。
Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。
具体应用
1)JavaBean 是 reflection 的实际应用之一,它能让一些工具可视化的操作软件组件。这些工具通过reflection 动态的载入并取得Java 组件(类) 的属性。
三个步骤:
第一步是获得你想操作的类的java.lang.Class对象。
Class c = Class.forName("java.lang.String");
这条语句得到一个 String 类的类对象(类的对象和类的类对象的区别)。
还有另一种方法,如下面的语句:
Class c = int.class;
或者
Class c = Integer.TYPE;
它们可获得基本类型的类信息。其中后一种方法中访问的是基本类型的封装类 (如 Integer) 中预先定义好的 TYPE 字段。
第二步是调用诸如getDeclaredMethods 的方法,以取得该类中定义的所有方法的列表。
第三步使用 reflection API 来操作这些信息
2)模拟 instanceof 操作符
Class.isInstance 方法可以用于模拟 instanceof 操作符:
Class cls = Class.forName("java.lang.String");
boolean b1 = cls.isInstance(new Integer(37)); //b1 = false
boolean b2 = cls.isInstance(new String("ab")); //b2 = true
3)找出类的方法
首先取得类的描述,然后调用 getDeclaredMethods 来获取一系列的 Method 对象,它们分别描述了定义在类中的每一个方法,包括public 方法、protected 方法、package 方法和 private 方法等。如果你在程序中使用getMethods来代替 getDeclaredMethods,你还能获得继承来的各个方法的信息。取得了 Method 对象列表之后,要显示这些方法的参数类型、异常类型和返回值类型等就不难了。这些类型是基本类型还是类类型,都可以由描述类的对象按顺序给。
4)获取构造器信息
5)获取类的字段(域)
Modifier,它也是一个 reflection 类,用来描述字段成员的修饰语,如“private int”。这些修饰语自身由整数描述,而且使用Modifier.toString 来返回以“官方”顺序排列的字符串描述(如“static”在final”之前)。和获取方法的情况一下,获取字段的时候也可以只取得在当前类中申明了的字段信息(getDeclaredFields),或者也可以取得父类中定义的字段(getFields) 。
6)根据方法的名称来执行方法
Method meth = cls.getMethod("add", partypes); //add方法名,参数类类型
method2 methobj = new method2();
Object retobj = meth.invoke(methobj, arglist); //methobj类实例 ,arglist参数
getMethod 用于查找一个具有两个整型参数且名为 add 的方法。找到该方法并创建了相应的 Method 对象之后,在正确的对象实例中执行它。执行该方法的时候,需要提供一个参数列表.
7)创建新的对象
对于构造器,则不能像执行方法那样进行,因为执行一个构造器就意味着创建了一个新的对象 (准确的说,创建一个对象的过程包括分配内存和构造对象)。
Constructor ct = cls.getConstructor(partypes); //partypes参数类类型
Object retobj = ct.newInstance(arglist); //arglist参数
根据指定的参数类型找到相应的构造函数并执行它,以创建一个新的对象实例。使用这种方法可以在程序运行时动态地创建对象,而不是在编译的时候创建对象,这一点非常有价值。
8)改变字段(域)的值
reflection 的还有一个用处就是改变对象数据字段的值。reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它
Class cls = Class.forName("field2");
Field fld = cls.getField("d");
field2 f2obj = new field2();
fld.setDouble(f2obj, 12.34);
10)使用数组
Class cls = Class.forName("java.lang.String");
Object arr = Array.newInstance(cls, 10);
Array.set(arr, 5, "this is a test");
String s = (String)Array.get(arr, 5);
System.out.println(s);
创建了 10 个单位长度的 String 数组,为第 5 个位置的字符串赋了值,最后将这个字符串从数组中取得并打印了出来。