工作需要用到类方法的反射调用,网上找到这样一段代码:
public static Object invokeMethod(Object object, String methodName, Class[] parameterTypes, Object... parameters) {
//根据 对象、方法名和对应的方法参数 通过反射 调用上面的方法获取 Method 对象
Method method = getDeclaredMethod(object, methodName, parameterTypes);
//抑制Java对方法进行检查,主要是针对私有方法而言
method.setAccessible(true) ;
try {
if(null != method) {
//调用object 的 method 所代表的方法,其方法的参数是 parameters
return method.invoke(object, parameters) ;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
哎,既然后面传入了 parameters,那么 parameterTypes 直接 parameters.getClass() 就好了,何必再传;
于是稍加修改,该方法变成这个样子:
public static Object invokeMethod(Object object, String methodName, Object... parameters) {
//根据 对象、方法名和对应的方法参数 通过反射 调用上面的方法获取 Method 对象
Class[] parameterTypes = new Class[parameters.length];
for(int i = 0; i < parameters.length; i++){
parameterTypes[i] = parameters[i].getClass();
}
Method method = getDeclaredMethod(object, methodName, parameterTypes);
//抑制Java对方法进行检查,主要是针对私有方法而言
method.setAccessible(true) ;
try {
if(null != method) {
//调用object 的 method 所代表的方法,其方法的参数是 parameters
return method.invoke(object, parameters) ;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
嗯,不禁为自己的机智点赞;
于是加入工程,跑起来,哎,怎么反射找不到方法;
仔细观察,调用时的代码是 ClassReflectionUtils.invokeMethod(obj, "func", 123);
调试步进,观察 paramters,发现变成了 Integer 类型;
原来立即数会被强转为这种“高级立即数类”;
那么再测试一下:
public static void fun(Object... args){
for(Object object : args){
Class xx = object.getClass();
System.out.println(xx);
}
return;
}
public static void main(String[] args) {
int m = 1;
double n = 2.3;
fun(m, n);
}
得到了如下输出:
嗯,看来确实会被强转,那么 invokeMethod 的 parameterTypes 参数是不可省略了,再恢复之前的 invokeMethod ,跑起来,成功了。
其实省略该参数还有一个问题,当 parameters.getClass() 为子类,而指定 method 中需要的父类时,findMethod 应该也找不到方法,这里感兴趣的读者可以自行测试一下。