我正在通过解释器进行代码的动态调用,但涉及到方法解析时,我开始陷入棘手和丑陋的领域,这些领域在JLS第15.12节中有所讨论。
当您知道所有参数的确切类型时,“简单”的选择方法是使用Class.getDeclaredMethod(String name, Class[] parameterTypes)
。也许您需要检查方法的可访问性和类的超类/超接口。
但是,这并不包括以下任何一种情况,因此它有点无用:
- 装箱/拆箱基本类型
- 子类型
- 可变参数
- 空参数(除非解释器知道类型; 在编译时,任何不确定性都将通过将null强制转换为类/接口来消除)
- 基本类型转换(不是Java的一部分,但在语言上下文中允许 - 例如Rhino Javascript,其中所有数字都是浮点数,因此Java代码可能会采用
int
,但调用者传递一个数字,该数字可以是int
或double
)
(下面是前三个示例的快速示例)
是否有任何知名框架库可帮助解决此问题?
package com.example.test.reflect;
import java.lang.reflect.Method;
public class MethodResolutionTest {
public void compute(int i) { /* implementation... */ }
public void compute(Long l) { /* implementation... */ }
public void compute(Object obj) { /* implementation... */ }
public void compute(String... strings) { /* implementation... */ }
public static void main(String[] args) {
Class<?> cl = MethodResolutionTest.class;
/* these succeed */
findAndPrintMethod(cl, "compute", int.class);
findAndPrintMethod(cl, "compute", Long.class);
findAndPrintMethod(cl, "compute", Object.class);
findAndPrintMethod(cl, "compute", String[].class);
/* these fail */
findAndPrintMethod(cl, "compute", Integer.class);
findAndPrintMethod(cl, "compute", long.class);
findAndPrintMethod(cl, "compute", MethodResolutionTest.class);
findAndPrintMethod(cl, "compute", String.class, String.class);
}
private static void findAndPrintMethod(Class<?> objectClass,
String methodName, Class<?>... parameterTypes)
{
try {
Method method = findMethod(objectClass, methodName,
parameterTypes);
System.out.println(method.toString());
}
catch (SecurityException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private static Method findMethod(Class<?> objectClass,
String methodName, Class<?>[] parameterTypes)
throws SecurityException, NoSuchMethodException
{
return objectClass.getDeclaredMethod(methodName, parameterTypes);
}
}