Reflection
1 介绍Class对象
一个Class对象描述一个类或原始的数据类型。每个类一开始加载时,都会创建一个Class对象,代表着它的类型信息。
虚拟机为每个类型管理着一个独一无二的Class对象。
有三种方法获得类的Class对象。
1)Class cl1 = Date.class; // if you import java.util.*;
Class cl2 = int.class;
Class cl3 = Double[].class;
2)String className = "java.util.Date";
Class cl = Class.forName(className);
如果指定的类不存在,抛出ClassNotFoundException
异常
3)Employee e;
. . .
Class cl = e.getClass();
使用类的对象的getClass()方法。
Class的方法getName()可以获得类的名字。
由于历史的原因,对于数组来说,class对象的getName() 方法将返回一个古怪的字符串:
· Double[].class.getName() returns "[Ljava.lang.Double;".
· int[].class.getName() returns "[I".
虚拟机里每个类型(类或原始数据类型等)对应着一个独一无二的Class对象来表示它的类型信息,所以可以用以下方法比较2个对象所属的类是否一样:
if ( e.getClass() = = Employee.class)… …
API:
- static Class forName(String className)
returns the Class object representing the class with name className.
- Object newInstance()
returns a new instance of this class.
2 使用反射机制分析类的结构
Using Reflection to Analyze the Capabilities of Classes
在包java.lang.reflect里,有三个类用来描述属性、方法、构造函数,分别为:Field、Method、Constructor.
Field类有getName()方法可以获得属性的名字,getType()方法返回一个Class对象,描述属性的数据类型。
Method和Constructor含有可以获得参数类型的方法,Method还有可以获得函数返回值类型的方法。
这3个类都含有getModifiers()的方法,用来获得修饰符(static,private,public,final等等这些),它返回一个整数,Modifier类含有多个静态方法对这个整数分析。例如:
isPublic, isPrivate, or isFinal ,来判断是否public,private,final。可以使用Modifierd.toString(int )方法返回修饰符的串。
Class的getFields, getMethods, and getConstructors方法的返回值是数组,分别是被分析类及其父类(即是整个继承树上的类)的public的属性、方法、构造函数的Field、Method、Constructor数组。
而getdeclaredFields, getDeclaredMethods, and getDeclaredConstructors 方法返回的是被分析类(不包括父类)的所有属性、方法、构造函数的Field、Method、Constructor数组,包括public的、private的、protected的等。
API
- Field[] getFields() 1.1
- Field[] getDeclaredFields() 1.1
The getFields method returns an array containing Field objects for the public fields of this class or its superclasses. The geTDeclaredField method returns an array of Field objects for all fields of this class. The methods return an array of length 0 if there are no such fields or if the Class object represents a primitive or array type.
- Method[] getMethods() 1.1
- Method[] getDeclaredMethods() 1.1
return an array containing Method objects: getMethods returns public methods and includes inherited methods; getdeclaredMethods returns all methods of this class or interface but does not include inherited methods.
- Constructor[] getConstructors() 1.1
- Constructor[] getDeclaredConstructors() 1.1
return an array containing Constructor objects that give you all the public constructors (for getConstructors) or all constructors (for getdeclaredConstructors) of the class represented by this Class object.
java.lang.reflect.Constructor 1.1
- Class getDeclaringClass()
returns the Class object for the class that defines this constructor, method, or field.
- Class[] getExceptionTypes() (in Constructor and Method classes)
returns an array of Class objects that represent the types of the exceptions thrown by the method.
- int getModifiers()
returns an integer that describes the modifiers of this constructor, method, or field. Use the methods in the Modifier class to analyze the return value.
- String getName()
returns a string that is the name of the constructor, method, or field.
- Class[] getParameterTypes() (in Constructor and Method classes)
returns an array of Class objects that represent the types of the parameters.
- Class getReturnType() (in Method classes)
returns a Class object that represents the return type.
java.lang.reflect.Modifier 1.1
- static String toString(int modifiers)
returns a string with the modifiers that correspond to the bits set in modifiers.
- static boolean isAbstract(int modifiers)
- static boolean isFinal(int modifiers)
- static boolean isInterface(int modifiers)
- static boolean isNative(int modifiers)
- static boolean isPrivate(int modifiers)
- static boolean isProtected(int modifiers)
- static boolean isPublic(int modifiers)
- static boolean isStatic(int modifiers)
- static boolean isStrict(int modifiers)
- static boolean isSynchronized(int modifiers)
- static boolean isVolatile(int modifiers)
These methods test the bit in the modifiers value that corresponds to the modifier in the method name.
3使用反射在RunTime分析对象
Using Reflection to Analyze Objects at Run Time
在运行时分析对象的具体内容,例如属性的值。
先看一个例子:
Employee harry = new Employee("Harry Hacker", 35000, 10, 1, 1989);
// the class object representing Employee
Class cl = harry.getClass();
// the name field of the Employee class
Field f = cl.getDeclaredField("name");
// the value of the name field of the harry object
// i.e., the String object "Harry Hacker"
Object v = f.get(harry);
但是,这个例子存在一个问题,由于name属性是private的,所以会抛出IllegalAccessException异常。你只能够使用Field的get方法去访问那些有访问权限的属性。
Java的安全机制可以允许你获知对象的拥有哪些属性,但不允许你获得它们的属性值,除非你有访问的权限。
Reflection的默认守则是要尊重Java的安全机制,However, if a Java program is not controlled by a security manager that disallows it, you can override access control. To do this, invoke the setAccessible method on a Field, Method, or Constructor object.
例如:
f.setAccessible(true); // now OK to call f.get(harry);
setAccessible是类AccessibleObject里定义的方法,它是Field、Method、Constructor的父类。
Field的get()方法返回一个对象,如果属性的数据类型是原始类型,则返回的是它们的包装类。或者可以使用getDouble等方法获取原始数据类型值。
同样,你同样可以使用set方法为某个对象的属性设置值。f.set(obj,value).
4方法的指针
Method Pointers!
表面上,Java不提供方法指针,Java的设计者们强调方法指针是危险的和易于引发错误。
然而,JDK1.1已经含有了方法指针,它是reflection package的副产品。
Method类提供了invoke方法去调用被分析对象的方法:
Object invoke(Object obj, Object... args)
第一个参数是被分析对象,后面的参数是调用被分析对象方法的输入参数(在JDK5.0以前,后面的参数采用一个数组表示,如果没有被分析对象的调用方法输入参数,则传入null)。
如果调用的是一个静态方法,则第一个参数被忽略,你可以传入null。
可以通过Class类的getMethods方法获取Method数组,还可以以下这种方法:
(JDK 5.0)
Method getMethod(String name, Class... parameterTypes)
第一个参数为方法名,后面的参数为方法的输入参数,通过这样的方式去定位到被分析类的某个方法。
For example, here is how you can get method pointers to the getName and raiseSalary methods of the Employee class:
Method m1 = Employee.class.getMethod("getName");
Method m2 = Employee.class.getMethod("raiseSalary", double.class);
(Before JDK 5.0, you had to package the Class objects into an array or to supply null if there were no parameters.)
API
- public Object invoke(Object implicitParameter, Object[] explicitParameters)
invokes the method described by this object, passing the given parameters and returning the value that the method returns. For static methods, pass null as the implicit parameter. Pass primitive type values by using wrappers. Primitive type return values must be unwrapped.