一、Java反射样例
设置任意对象的属性值的JavaScirpt实现
function invokeSetter(obj, property,value){ var funcName = "set" + property.subString(0,1).toUpperCase() + property.substring(1); obj[funcName](value); } var obj = { value : 0 , setVale: function(val) { this.value = val; } }; invokeSetter(obj, "value", 5);通过Java反射API 实现同样功能,假设java中的属性都有setter和getter。
public static void invokeSetter(Object obj, String field, Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { String methodName = "set" + field.substring(0, 1).toUpperCase() + field.substring(1); Class<?> clazz = obj.getClass(); Method = method = clazz.getMethod(methodName, value.getClass()); method.invoke(obj, value); }常用场景:
1、Servlet中的HTTP请求的参数值来填充 领域对象(springMVC 中的 POJO)
2、数据库操作 从SQL回来的结构填充到领域对象。
二、获取构造方法
class对象的对应方法:
getConstructors获取所有公开的构造方法列表
getConstructor 根据参数获取公开的构造方法。
getDeclaredConstructors 获取声明的构造方法列表
getDeclaredConstructor 根据参数获取声明的开工构造方法。
特例:变长参数的构造方法获取
public class A{ public A(String... names){} } public void useA() throws Exception{ Constructor<A> constructor = A.class.getDeclaredContructor(String[].class);//变长参数底层就是数组实现 constructor.newInstance((Object) new String[]{"A","B","C"}); }//<span style="font-family: Arial, Helvetica, sans-serif;">实际使用需要转换为Object类型,编译器就知道这个字符串数组作为变长参数传递</span>
获取公开的域
Field fCount = B.class.getDeclaredField("count"); fCount.set(null, 3);//静态域 Field fName = B.class.getDeclaredField("name"); B b = new B(); fName.set(b, "Bob");//实例域Field出了提供操作Object 的set和get,还有一堆setBoolean/getBoolean,和其他所有基本类型的s/g.
四、获取方法
class的四个方法, 和构造方法一样,不解释。
getMethods
getMethod
getDeclaredMethods
getDeclaredMethod
A a = new A(); Method publicM = A.class.getDeclaredMethod("publicMethod"); publicM.invoke(a); Method privateM = A.class.getDeclaredMethod("privateMethod"); privateM.setAccessible(true);//构造方法和域不具备,反射可以获得私有方法并修改访问权限。 privateMethod.invoke(a);
与一般Java对象不同,数组通过 java.lang.reflect.Array来访问。
String[] names = (String[]) Array.newInstance(String.class, 10); names[0] = "Hello"; Array.set(names, 1, "World"); String str = (String) Array.get(names, 0); int [][][] matrix1 = (int[][][]) Array.newInstance(int.class, 3, 3, 3); matrix1[0][0][0] = 1; int [][][] matrix2 = (int[][][]) Array.newInstance(int[].class, 3, 4); matrix[0][0] = new int[10]; matrix[0][0][0] = 1;
1、通过反射可以访问对象的私有方法
2、invoke方法调用方法,如果方法本身抛出异常,invoke方法会抛出InvocationTargetException异常
捕获后,通过InvocationTargetException异常的getCause方法获得真正的异常信息。
3、java7 给所有与反射操作相关的异常添加了一个新的父类java.lang.ReflectiveOperationException,可以直接捕获之,过去这些异常需要分别捕获。