一、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,可以直接捕获之,过去这些异常需要分别捕获。