方法中带有超类参数的Java getMethod

方法中带有超类参数的Java getMethod,java,reflection,Java,Reflection,鉴于: 假设我想通过反射调用方法m,将ArrayList作为参数传递给m: class A { public void m(List l) { ... } } 第3行的getMethod将抛出NoSuchMethodException,因为myList的运行时类型是ArrayList,而不是List 有没有一种好的通用方法不需要了解类a的参数类型?而不是myList.getClass(),为什么不直接传入List.class?这就是您的方法所期望的。如果您知道类型是List,则使用Li

鉴于:

假设我想通过反射调用方法
m
,将ArrayList作为参数传递给
m

class A
{
    public void m(List l) { ... }
}
第3行的
getMethod
将抛出
NoSuchMethodException
,因为myList的运行时类型是ArrayList,而不是List


有没有一种好的通用方法不需要了解类a的参数类型?

而不是
myList.getClass()
,为什么不直接传入
List.class
?这就是您的方法所期望的。

如果您知道类型是
List
,则使用
List.class
作为参数

如果您事先不知道类型,请想象您有:

List myList = new ArrayList();
A a = new A();
Method method = A.class.getMethod("m", new Class[] { myList.getClass() });
method.invoke(a, Object[] { myList });
如果有自动方法,反射应该调用哪个方法

如果需要,可以使用
Class.getInterfaces()
Class.getSuperclass()
,但这是特定于大小写的

您可以在这里做的是:

public void m(List l) {
 // all lists
}

public void m(ArrayList l) {
  // only array lists
}
public void invoke(对象targetObject,对象[]参数,
字符串方法名){
对于(方法:targetObject.getClass().getMethods()){
如果(!method.getName().equals(methodName)){
继续;
}
类[]parameterTypes=method.getParameterTypes();
布尔匹配=真;
对于(int i=0;i
我猜您想要
getDeclaredMethods()
。这是一个例子。您可以仔细查看方法列表,并按名称选择所需的方法。这是健壮的还是好主意是另一个问题。

请参阅java.beans.Expression和java.beans.Statement。

我实际上不知道调用的方法是什么。不仅仅是
m
,还有许多具有不同参数类型的方法。您需要事先知道要调用什么。反射不像魔法。您需要知道希望通过反射访问的方法名和方法签名。有时,您还需要知道需要调用的方法的版本(.ie.您需要访问由您的一个超类定义的方法“m”的版本。@luis:我同意您的观点,即反射不会帮助您选择方法,但我不同意您需要事先知道要调用的确切方法。在解释器/动态语言上下文中,您所拥有的只是方法名argu如果幸运的话,您从用户那里得到了一些提示。反射API提供的原始资料与根据参数类型选择适用方法之间的差距必须由解释器应用程序级别的某些东西提供。@Jason在解释器/动态语言上下文中,您(可能)没有方法重载,所以您可以(可能)找出哪种方法应该只按名称调用。@Jason-我关于需要事先知道该方法的评论是在Java的上下文中。提到解释器/动态语言的反射功能,尽管它们本身很有趣,但与最初提出OP问题的上下文不符。我我事先不知道类型。如果我的l.getClass()返回ArrayList作为运行时类型,但可能我期望的太多了?没错。但是您希望根据第二个方法是否存在来执行第一个方法。您不能这样做。因此,实际获取
m1
的唯一方法是尝试对不同参数的超类和接口进行各种排列,而这些参数不是版本好主意。确切地说,你不想做所有这些排列。在一些非常特殊的情况下-。例如,你正在构建一个框架或解释器,或者需要与(可能写得不好)接口第三方库,您需要这样做。但是,生成的代码非常脆弱。反射只是访问类定义的工件的另一种方式。在这种情况下,访问是动态的,而不是静态编译的。但是知道需要调用什么的要求保持不变。如果您确实不知道l类型,而需求需要您在不知道该类型信息的情况下进行操作,我要说的是:谨慎行事。一般来说,我会采取类似代码(或需求)气味的情况,需要重新审视。谢谢,我确实知道这一点,但我不想诉诸于此。不过,我可能不得不这样做。
public void invoke(Object targetObject, Object[] parameters,
        String methodName) {
    for (Method method : targetObject.getClass().getMethods()) {
        if (!method.getName().equals(methodName)) {
            continue;
        }
        Class<?>[] parameterTypes = method.getParameterTypes();
        boolean matches = true;
        for (int i = 0; i < parameterTypes.length; i++) {
            if (!parameterTypes[i].isAssignableFrom(parameters[i]
                    .getClass())) {
                matches = false;
                break;
            }
        }
        if (matches) {
            // obtain a Class[] based on the passed arguments as Object[]
            method.invoke(targetObject, parametersClasses);
        }
    }
}