一、反射
Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。
Java反射机制主要提供了以下功能:
- 在运行时构造任意一个类的对象
- 在运行时获取任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法(属性)
- 生成动态代理
二、Method基础
/**
* Class 是对一个类的描述
* 类的属性: Field
* 类的方法: Method
* 类的构造器: Constructor
*
* Method: 对应类中的方法
* 1.获取Method
* 1.1 获取类的方法数组:getDeclaredMethods()
* 1.2 获取指定的方法:
* public Method getDeclaredMethod(String name,
* Class<?>... parameterTypes)
* name - the name of the method
* parameterTypes - the parameter array
*
* 1.3 用过 Method对象执行方法
* public Object invoke(Object obj,
* Object... args)
* obj - the object the underlying method is invoked from
* args - the arguments used for the method call
*
*/
@Test
public void test4() throws Exception{
String className = "com.wang.reflection.Person";
Class clazz = Class.forName(className);
//1. 得到clazz对应类中的方法,不能获取私有方法
Method[] methods = clazz.getMethods();
for(Method method : methods) {
System.out.println("1." + method);
}
System.out.println();
//2.获取所有方法,包括私有,且只获取当前类声明的方法
Method[] methods2 = clazz.getDeclaredMethods();
for(Method method : methods2) {
System.out.println("2." + method);
}
System.out.println();
//3.获取指定的方法
Method method = clazz.getDeclaredMethod("test");
System.out.println("3." + method);
method = clazz.getDeclaredMethod("setName", String.class);
System.out.println("3." + method);
System.out.println();
//4.执行方法
System.out.println("4.");
Object obj = clazz.newInstance();
method.invoke(obj,"wang");
}
执行结果:
写一个方法:
/**
* 通过一个类的全类名、方法名和参数来执行该方法
*
* @param className 某个类的全类名
* @param methodName 类的一个方法名
* @param args 需要的参数
* @return 方法的返回值
*/
public Object invoke(String className, String methodName, Object ... args) {
try {
Object obj = Class.forName(className).newInstance();
return invoke(obj, methodName, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 通过一个方法的对象、名称、参数来执行该方法
*
* @param obj 要执行的方法的对象
* @param methodName 要执行的方法名
* @param args 要执行方法的参数
* @return 方法的返回值
*/
public Object invoke(Object obj, String methodName, Object ... args) {
//1. 获取Method对象
Class [] parameterTypes = new Class[args.length];
for(int i = 0; i < args.length; ++i) {
parameterTypes[i] = args[i].getClass();
}
try {
Method method = obj.getClass().getMethod(methodName, parameterTypes);
//2.执行Method方法,并返回值
return method.invoke(obj,args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Test
public void test5() {
Object result =
invoke("java.text.SimpleDateFormat", "format", new Date());
System.out.println(result);
}
执行结果:
三、获取并执行父类的私有方法
(1)获取父类的私有方法
/**
* 获取当前类的父类
* 直接调用 Class对象的 getSuperclass()方法
*/
@Test
public void test6() throws Exception {
String className = "com.wang.reflection.Student";
Class clazz = Class.forName(className);
Class superClazz = clazz.getSuperclass();
System.out.println(superClazz);
}
(2)invoke() 调用私有方法
/**
* 若通过 Method的 invoke()调用私有方法,需要执行:
* method.setAccessible(true);
*
*/
@Test
public void test7() throws Exception {
Object obj = new Student();
Class clazz = obj.getClass();
Method method = clazz.getDeclaredMethod("method1", Integer.class);
System.out.println(method);
//若要通过反射执行私有方法
method.setAccessible(true);
method.invoke(obj, 10);
}
(3)获取当前类或父类中的方法
/**
* 获取 clazz的 methodName方法,该方法可能是私有方法,也可能是父类中的(私有方法)
* @param clazz clazz
* @param methodName 方法名称
* @param parameterTypes 方法参数
* @return Method
*/
public Method getMethod(Class clazz, String methodName, Class ... parameterTypes) {
for(; clazz != Object.class; clazz = clazz.getSuperclass()) {
try {
Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
return method;
} catch (Exception e) { }
}
return null;
}
@Test
public void test8() {
try {
Class clazz = Class.forName("com.wang.reflection.Student");
Method method = getMethod(clazz, "method1", Integer.class);
System.out.println("method");
method = getMethod(clazz,"method2");
System.out.println(method);
} catch (Exception e) {
e.printStackTrace();
}
}
四、执行一个方法
执行一个方法,只要提供类的全类名,方法名和参数,就可执行一个方法,不管是共有方法还是私有方法,不管是在当前类中环是在父类中。
修改之前的invoke方法:
/**
* 通过一个类的全类名、方法名和参数来执行该方法
* 不管这个方法是共有方法还是私有方法,不管在当前类中还是父类中。
*
* @param className 某个类的全类名
* @param methodName 类的一个方法名
* @param args 需要的参数
* @return 方法的返回值
*/
public Object invoke(String className, String methodName, Object ... args) {
try {
Object obj = Class.forName(className).newInstance();
return invoke(obj, methodName, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 通过一个方法的对象、名称、参数来执行该方法
*
* @param obj 要执行的方法的对象
* @param methodName 要执行的方法名
* @param args 要执行方法的参数
* @return 方法的返回值
*/
public Object invoke(Object obj, String methodName, Object ... args) {
//1. 获取Method对象
Class [] parameterTypes = new Class[args.length];
for(int i = 0; i < args.length; ++i) {
parameterTypes[i] = args[i].getClass();
}
try {
//修改1:getMethod方法可以获得当前类或者父类的任何方法
Method method = getMethod(obj.getClass(), methodName, parameterTypes);
//2.设置可以执行私有方法
//修改2:共有、私有方法都可以执行
method.setAccessible(true);
//3.执行Method方法,并返回值
return method.invoke(obj,args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Test
public void test9() throws Exception {
invoke("com.wang.reflection.Student", "method1", 18);
Object obj = invoke("com.wang.reflection.Student", "method2");
System.out.print(obj);
}
1. Java基础--反射之Class类 http://my.oschina.net/daowuming/blog/703293
2. Java基础--反射之Method ----当前----
3. Java基础--反射之Field http://my.oschina.net/daowuming/blog/703605