我正在编写一个使用反射来动态查找和调用方法的库.只给出一个对象,一个方法名和一个参数列表,我需要调用给定的方法,就好像方法调用是在代码中显式编写的一样.
我一直在使用以下方法,在大多数情况下都可以使用:
static void callMethod(Object receiver, String methodName, Object[] params) {
Class<?>[] paramTypes = new Class<?>[params.length];
for (int i = 0; i < param.length; i++) {
paramTypes[i] = params[i].getClass();
}
receiver.getClass().getMethod(methodName, paramTypes).invoke(receiver, params);
}
但是,当其中一个参数是方法支持的类型之一的子类时,反射API会抛出NoSuchMethodException.例如,如果接收者的类定义了testMethod(Foo),则以下操作失败:
receiver.getClass().getMethod("testMethod", FooSubclass.class).invoke(receiver, new FooSubclass());
尽管这有效:
receiver.testMethod(new FooSubclass());
我该如何解决这个问题?如果方法调用是硬编码的,则没有问题 – 编译器只使用重载算法来选择最适用的方法.但它不适用于反射,这是我需要的.
提前致谢!
解决方法:
它比你开始时要长一些,但是这样做你要求的……还有一点 – 例如,callMethod(接收器,“voidMethod”),其中voidMethod不带参数也可以.
static void callMethod(Object receiver,
String methodName, Object... params) {
if (receiver == null || methodName == null) {
return;
}
Class<?> cls = receiver.getClass();
Method[] methods = cls.getMethods();
Method toInvoke = null;
methodLoop: for (Method method : methods) {
if (!methodName.equals(method.getName())) {
continue;
}
Class<?>[] paramTypes = method.getParameterTypes();
if (params == null && paramTypes == null) {
toInvoke = method;
break;
} else if (params == null || paramTypes == null
|| paramTypes.length != params.length) {
continue;
}
for (int i = 0; i < params.length; ++i) {
if (!paramTypes[i].isAssignableFrom(params[i].getClass())) {
continue methodLoop;
}
}
toInvoke = method;
}
if (toInvoke != null) {
try {
toInvoke.invoke(receiver, params);
} catch (Exception t) {
t.printStackTrace();
}
}
}