{$PageTitle=}
【IT168技术文档】
Java Reflection(反射)是一种在运行期间查看Java对象内部情况的技术,包括Java对象的变量、支持的方法、实现的接口、扩展的类——基本上在编译时你能想知道的关于对象的任何东西。
Reflection API位于java.lang.reflect包中,在所有J2SE安装程序中都有。它主要是为一些通用程序设计的,如数据库浏览器或可视代码编辑器,但是它可以被运用在其他任何应用软件中。Reflection用于处理之前你所知甚少的类文件。反射需要很高的间接制造费用,所以在使用之前,你应该确定自己不能仅凭一个简单的接口——Class.forName(),而要用一个委托对象。
实例
列表 A含有一个使用Reflection代码的例子。列表A中的代码与下列代码等同:
newTestClass().setName("TestName");
第一个例子中的代码用反射动态地调用新建对象的方法。这使用起来相当方便,但相对较慢。
基本技巧
Reflection中包含了两种基本的技术:探索和按名称使用。以下是对两种方法的描述:
探索指采用一个对象或类,并发现其成员、超类、实现的接口,然后尽可能地使用被发现的元素。
按名字使用指以一个元素的符号名开始,并使用已命名的元素。
通常,探索方法以一个对象开始,并通过调用Object.getClass()方法获得对象的类。类对象有很多方法发现类的内容。以下是部分方法:
getMethods():返回一组表示类或接口的所有公共方法的方法对象数组。
getConstructors():返回一组表示类的所有公共构造器的构造器对象数组。
getFields():返回一组表示类或接口所有公共字段的字段对象数组。
getClasses():返回一组表示所有属于类或接口的公共类和接口(例如,内部类)的类对象数组。
getSuperclass():返回表示类或接口的超类的类对象(接口返回为空值)。
getInterfaces():返回一组表示类或接口执行的所有接口的类对象数组。
你可以通过探索,即应用类字面(如MyClass.class)或使用类名(如Class.forName("mypackage.MyClass"))获得类对象。有了类对象,成员对象方法、构造器或字段可以通过使用成员的符号名获得。以下是最重要的一些技术:
getMethod("methodName", Class...):返回表示接受类参数指定参数的类或接口中名为“methodName”的公共方法的方法对象。
getConstructor(Class...):返回表示接受类参数指定参数的类公共构造器的构造器对象。
getField("fieldName"):返回表示类或接口中名为“fieldname”的公共字段的字段对象。
你可以使用Method、Constructor和Field(字段)对象动态地访问类表示成员。例如:
Field.get(Object):返回一个包含输入get()对象实例的字段值对象。(如果字段对象表示静态字段,那么对象参数便被忽略,也可能为空。)
Method.invoke(Object, Object...):返回一个包含为输入invoke()的第一个对象参数实例调用方法的结果的对象。其余对象参数被传递给输入方法。(如果方法对象表示一个静态方法,那么第一个对象参数便被忽略,也可能为空。)
Constructor.newInstance(Object...):返回调用构造器的新对象实例。对象参数输入构造器。(注意类的无参数构造器也可以通过newInstance()被调用。)
创建数组和代理类
java.lang.reflect包提供一个数组,其中包含了可创建和操控数组对象的静态方法。从J2SE 1.3开始,java.lang.reflect包还提供了一个代理类,它支持动态创建用来实现指定接口的代理类。
代理类的执行由执行InvocationHandler接口的一个补充对象完成。代理对象的每个调用方法调用InvocationHandler的方法调用(对象、方法、对象[])——第一参数是代理对象,第二参数是表示代理所执行接口的方法的方法对象,而第三参数是输入接口方法的参数数组。invoke()方法返回一个对象结果,其中包含返回调用代理接口方法的代码的结果。