java在将int类型的数据传递给Object的对象时会自动装箱为Integer对象,从而在获取数据的class对象时获取的是Integer.class,而不是int.class==Integer.TYPE。
java反射传参时int被装箱Integer实例
package reflect;
import java.lang.reflect.Method;
public class TInvoke {
/**
* 获取clazz 的methodName 方法, 该方法可能是私有方法
*/
public Method getMethod(Class clazz, String methodName, Class ... parameterTypes) {
//注意这个循环里的内容!!!
for (; clazz != Object.class; clazz = clazz.getSuperclass()){
try {
return clazz.getDeclaredMethod(methodName, parameterTypes);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* @param className 某个类的全类名
* @param methodName 类的一个方法的方法名,该方法也可能是私有方法
* @param args 调用该方法需要传入的参数 ...可变参数的意思
* @return 调用方法后的返回值
*/
public Object invoke(String className, String methodName, Object ... args) {
Object obj = null;
try {
obj = Class.forName(className).newInstance();
return invoke(obj, methodName, args);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return invoke(null, methodName, args);
}
/**
* @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 {
//2、执行Method方法
Method method = getMethod(obj.getClass(), methodName,parameterTypes);
//通过反射执行private方法
method.setAccessible(true);
//3、返回方法的返回值
return method.invoke(obj,args);
} catch (Exception e) {
}
return null;
}
public void testInvoke(){
Object obj = new TMethod();
invoke(obj, "test3","test3",10);
Object result = invoke(obj, "test2","test2");
System.out.println(result);
}
public static void main(String[] args) {
try {
TInvoke obj = new TInvoke();
obj.testInvoke();
} catch (Exception e) {
e.printStackTrace();
}
}
}
1、如上,我们将方法名,方法参数和类对象或者类的class对象传递给invoke方法
invoke(String className, String methodName, Object … args),当我们传递的参数包含int,boolean等是会自动装箱成Integer,Boolean
2、接下来我们根据invoke方法参数获取需要执行方法参数的Class类型,进而根据方法名称和方法的参数的Class类型获取需要执行的方法对象
clazz.getDeclaredMethod(methodName, parameterTypes);
3、 进而执行方法
method.invoke(obj,args);
4、以上代码输出如下
java.lang.NoSuchMethodException: reflect.TMethod.test3(java.lang.String, java.lang.Integer)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at reflect.TInvoke.getMethod(TInvoke.java:13)
at reflect.TInvoke.invoke(TInvoke.java:57)
at reflect.TInvoke.testInvoke(TInvoke.java:74)
at reflect.TInvoke.main(TInvoke.java:83)
私有测试方法2,参数String=test2
null
可以看到找不到方法,因为方法的参数类型是(java.lang.String ,int)类型,而我们获取的是(java.lang.String, java.lang.Integer)类型,与实际的方法参数类型不符,无法找到该方法
这是由于int类型的自动封装造成的,那么该怎么解决呢?
我们获取方法的参数类型不对,在根据参数获取参数类型的时候出错,那么我们就从根源上解决这个问题
在传递参数的同时,传递方法参数的类型,手动传入参数类型就不会出现根据参数获取参数类型的错误了
通用解决方法
package reflect;
import java.lang.reflect.Method;
public class TInvokeT {
/**
* 获取clazz 的methodName 方法, 该方法可能是私有方法
*/
public Method getMethod(Class clazz, String methodName, Class ... parameterTypes) {
//注意这个循环里的内容!!!
for (; clazz != Object.class; clazz = clazz.getSuperclass()){
try {
return clazz.getDeclaredMethod(methodName, parameterTypes);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* @param className 某个类的全类名
* @param methodName 类的一个方法的方法名,该方法也可能是私有方法
* @param args 调用该方法需要传入的参数 ...可变参数的意思
* @return 调用方法后的返回值
*/
public Object invoke(String className, String methodName,Class<?>[] parameterTypes,Object ... args) {
Object obj = null;
try {
obj = Class.forName(className).newInstance();
return invoke(obj, methodName, parameterTypes,args);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return invoke(null, methodName,parameterTypes, args);
}
/**
* @param obj 方法执行的那个对象
* @param methodName 类的一个方法的方法名,该方法也可能是私有方法,还可能是该方法在父类中定义的私有方法
* @param args 调用该方法需要传入的参数 ...可变参数的意思
* @return 调用方法后的返回值
*/
public Object invoke(Object obj, String methodName,Class<?>[] parameterTypes, Object ... args) {
try {
//2、执行Method方法
Method method = getMethod(obj.getClass(), methodName,parameterTypes);
//通过反射执行private方法
method.setAccessible(true);
//3、返回方法的返回值
return method.invoke(obj,args);
} catch (Exception e) {
}
return null;
}
public void testInvoke(){
Object obj = new TMethod();
invoke(obj, "test3",new Class<?>[] {String.class,int.class},"test3",10);
Object result = invoke(obj, "test2",new Class<?>[] {String.class},"test2");
System.out.println(result);
}
public static void main(String[] args) {
try {
TInvokeT obj = new TInvokeT();
obj.testInvoke();
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出如下
公有测试方法3,参数String=test3:num=10
私有测试方法2,参数String=test2
null
invoke(obj, “test2”,new Class>[] {String.class},”test2″);
invoke方法在传入参数值的同时传入参数的类型的数组
invoke(Object obj, String methodName,Class>[] parameterTypes, Object … args)
invoke方法获取参数值的同时获取参数的类型,直接使用参数类型,不必获取就不存在参数类型获取错误的问题