参考:
【1】http://dev.csdn.net/article/49/49876.shtm
【2】http://tutorials.jenkov.com/java-reflection/index.html
Java reflection
什么是java反射机制? java机制能干什么?
从理论上说,java reflection 就是对运行中的class进行“自审”。允许程序对运行中的类、接口等重的属性、方法进行检测。常用的地方有:java bean、Hibernate的数据库映射等。
java reflection的包“java.lang.reflect”。
1.获取操作类的java.lang.Class对象:
Class c = Class.forName("java.lang.String"); Class c = int.class; Class c = Integer.TYPE;
2.获取诸如getDeclearedMethods方法,以取得该类中定义的所有方法的列表。
Class c = Class.forName("java.lang.String"); Method m[] = c.getDeclearedMethods();
3.操作这些信息
System.out.println(m[0].toString());
常用操作:
1.获取类的methods
Class c = Class.forName("constructor1"); Method[] m[] = c.getDeclearedMethods();
getDeclearedMethods()://获取类中所有方法。
getMethods()://还可以获取继承来的各个方法信息。
2.获取构造器
Class cls = Class.forName("constructor1"); Constructor ctorlist[] = cls.getDeclaredConstructors();
3.获取所有属性
Class cls = Class.forName("reflection.field1"); Field fieldlist[] = cls.getDeclaredFields();
4.根据方法的名称来执行方法
import java.lang.reflect.Method; /* * 根据方法的名称来执行方法 */ public class Method2 { public int add(int a, int b) { return a + b; } public static void main(String args[]) { try { Class cls = Class.forName("reflection.method2"); // 用于查找一个具有两个整型参数且名为 add 的方法 Class partypes[] = new Class[2]; partypes[0] = Integer.TYPE; partypes[1] = Integer.TYPE; Method meth = cls.getMethod("add", partypes); // 实例化对象,并构造参数列表 Method2 methobj = new Method2(); Object arglist[] = new Object[2]; arglist[0] = new Integer(37); arglist[1] = new Integer(47); // 执行方法,并获取结果 Object retobj = meth.invoke(methobj, arglist); Integer retval = (Integer) retobj; System.out.println(retval.intValue()); } catch (Throwable e) { System.err.println(e); } } }
5.执行构造器,创建新的对象实例
package reflection; import java.lang.reflect.*; public class constructor2 { public constructor2() { } public constructor2(int a, int b) { System.out.println("a = " + a + " b = " + b); } public static void main(String args[]) { try { Class cls = Class.forName("reflection.constructor2"); // 用于查找一个具有两个整型参数的构造方法 Class partypes[] = new Class[2]; partypes[0] = Integer.TYPE; partypes[1] = Integer.TYPE; Constructor ct = cls.getConstructor(partypes); // 构造参数列表 Object arglist[] = new Object[2]; arglist[0] = new Integer(37); arglist[1] = new Integer(47); // 执行方法,并获取对象实例 Object retobj = ct.newInstance(arglist); } catch (Throwable e) { System.err.println(e); } } }
6.改变字段(域)的值
reflection 的还有一个用处就是改变对象数据字段的值。reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它,下面的例子可以说明这一点:
import java.lang.reflect.*; public class field2 { public double d; public static void main(String args[]) { try { Class cls = Class.forName("field2"); Field fld = cls.getField("d"); field2 f2obj = new field2(); System.out.println("d = " + f2obj.d); fld.setDouble(f2obj, 12.34); System.out.println("d = " + f2obj.d); } catch (Throwable e) { System.err.println(e); } } }
这个例子中,字段 d 的值被变为了 12.34。
7.使用数组
创建的操作数组。数组在 Java 语言中是一种特殊的类类型,一个数组的引用可以赋给 Object 引用。观察下面的例子看看数组是怎么工作的:
import java.lang.reflect.*; public class array1 { public static void main(String args[]) { try { 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); } catch (Throwable e) { System.err.println(e); } } }
例中创建了 10 个单位长度的 String 数组,为第 5 个位置的字符串赋了值,最后将这个字符串从数组中取得并打印了出来。
下面这段代码提供了一个更复杂的例子:
import java.lang.reflect.*; public class array2 { public static void main(String args[]) { int dims[] = new int[]{5, 10, 15}; Object arr = Array.newInstance(Integer.TYPE, dims); Object arrobj = Array.get(arr, 3); Class cls = arrobj.getClass().getComponentType(); System.out.println(cls); arrobj = Array.get(arrobj, 5); Array.setInt(arrobj, 10, 37); int arrcast[][][] = (int[][][]) arr; System.out.println(arrcast[3][5][10]); } }
例中创建了一个 5 x 10 x 15 的整型数组,并为处于 [3][5][10] 的元素赋了值为 37。注意,多维数组实际上就是数组的数组,例如,第一个 Array.get 之后,arrobj 是一个 10 x 15 的数组。进而取得其中的一个元素,即长度为 15 的数组,并使用 Array.setInt 为它的第 10 个元素赋值。
注意创建数组时的类型是动态的,在编译时并不知道其类型。
------------class--------
8.获取类名
// 获取类的全名(包名+类名) Class aClass = MyObject.class; String className = aClass.getName(); // 获取类名(不包含包名) Class aClass = MyObject.class; String simpleClassName = aClass.getSimpleName();
9.获取修饰符
int mod = *.getModifiers(); Modifier.toString(mod));
10.获取包信息
Package package = aClass.getPackage();
11.获取父类
Class superclass = aClass.getSuperclass();
12.获取实现的接口
Class[] interfaces = aClass.getInterfaces();
13.others
Constructor[] constructors = aClass.getConstructors(); Method[] method = aClass.getMethods(); Method[] method = aClass.getFields();
-------Constructor ------------
14.获取构造方法
Class aClass = ...//obtain class object Constructor[] constructors = aClass.getConstructors(); // 如果你已经知道构造方法的参数,也可以用以下代码获取具体方法 Class aClass = ...//obtain class object Constructor constructor = aClass.getConstructor(new Class[]{String.class});
15.获取构造方法的参数信息
Constructor constructor = ... // obtain constructor - see above Class[] parameterTypes = constructor.getParameterTypes();
16.实例化对象
//get constructor that takes a String as argument Constructor constructor = MyObject.class.getConstructor(String.class); MyObject myObject = (MyObject) constructor.newInstance("constructor-arg1");// 实际参数列表
---------Fileds------------------
16.获取属性信息
Class aClass = ...//obtain class object Field[] methods = aClass.getFields(); // 如果你知道属性名字 Class aClass = MyObject.class Field field = aClass.getField("someField");
17.获取属性名字
Field field = ... //obtain field object String fieldName = field.getName();
18.获取属性类型
Field field = aClass.getField("someField"); Object fieldType = field.getType();
19.获取或设置属性值
Class aClass = MyObject.class Field field = aClass.getField("someField"); MyObject objectInstance = new MyObject(); // 获取属性值 Object value = field.get(objectInstance); // 设置属性值 field.set(objetInstance, value);
------------Methods-------------
20.获取方法
Class aClass = ...//obtain class object Method[] methods = aClass.getMethods(); // 获取具体的某一方法,有参数 Class aClass = ...//obtain class object Method method = aClass.getMethod("doSomething", new Class[]{String.class}); // 获取具体的某一方法,无参数 Class aClass = ...//obtain class object Method method = aClass.getMethod("doSomething", null);
21.获取方法的参数或返回类型
Method method = ... // obtain method - see above Class[] parameterTypes = method.getParameterTypes(); Class returnType = method.getReturnType();
22.使用method对象执行方法
//get method that takes a String as argument Method method = MyObject.class.getMethod("doSomething", String.class); Object returnValue = method.invoke(null, "parameter-value1");
----------gets & sets----------------
23.set/get方法
public static void printGettersSetters(Class aClass){ Method[] methods = aClass.getMethods(); for(Method method : methods){ if(isGetter(method)) System.out.println("getter: " + method); if(isSetter(method)) System.out.println("setter: " + method); } } public static boolean isGetter(Method method){ if(!method.getName().startsWith("get")) return false; if(method.getParameterTypes().length != 0) return false; if(void.class.equals(method.getReturnType()) return false; return true; } public static boolean isSetter(Method method){ if(!method.getName().startsWith("set")) return false; if(method.getParameterTypes().length != 1) return false; return true; }
----------访问私有属性(private fileds)---------------
24.访问私有属性
Class.getField(String name) 和 Class.getFields() 只能获取public的属性;
如果想获取私有属性,你需要使用:Class.getDeclaredField(String name) 或 Class.getDeclaredFields()
一般来说,一个类的私有属性在类之外是不能访问的,可通过java反射机制,却能够做到这一点。
示例代码:
类:
public class PrivateObject { private String privateString = null; public PrivateObject(String privateString) { this.privateString = privateString; } }
私有属性访问代码
PrivateObject privateObject = new PrivateObject("The Private Value"); Field privateStringField = PrivateObject.class. getDeclaredField("privateString"); privateStringField.setAccessible(true);// 将该属性设置为可见 // 你可以访问私有属性了,呵呵 String fieldValue = (String) privateStringField.get(privateObject); System.out.println("fieldValue = " + fieldValue);
-----------access private methods---------------
25.和上一个比较类似
类:
public class PrivateObject { private String privateString = null; public PrivateObject(String privateString) { this.privateString = privateString; } private String getPrivateString(){ return this.privateString; } }
代码:
PrivateObject privateObject = new PrivateObject("The Private Value"); Method privateStringMethod = PrivateObject.class. getDeclaredMethod("getPrivateString", null); privateStringMethod.setAccessible(true); String returnValue = (String) privateStringMethod.invoke(privateObject, null); System.out.println("returnValue = " + returnValue);
---------------Array---------------------
26.创建Array
创建一个int[3],第一个参数类型,第二个参数大小
int[] intArray = (int[]) Array.newInstance(int.class, 3);
27.访问数组
int[] intArray = (int[]) Array.newInstance(int.class, 3); Array.set(intArray, 0, 123); Array.set(intArray, 1, 456); Array.set(intArray, 2, 789); System.out.println("intArray[0] = " + Array.get(intArray, 0)); System.out.println("intArray[1] = " + Array.get(intArray, 1)); System.out.println("intArray[2] = " + Array.get(intArray, 2));
--------------others----------------------
另外java反射机制还可以访问:注释Annotations、泛型Generics、代理Proxies什么的。。。。。。。
因为太晚了缘故 暂时到这,以后再补充吧