使用子类作为方法参数调用 getMethod 方法

3

是否可能调用一个参数对象或参数类是子类,而方法本身以超类作为参数的方法?

我试图使用抽象类Problem的具体实现来调用此方法public void setNewProblem(Problem problem);。不幸的是,我遇到了NoSuchMethodException异常。

我像这样调用invoke:

Method method = model.getClass().getMethod("set" + propertyName, new Class[] { newValue.getClass() });
method.invoke(model, newValue);

如果我将 newValue.getClass() 更改为 Problem.class,一切都可以正常工作。有什么想法如何将子类传递给 public void setNewProblem(Problem problem);

3
异常并非由invoke()引起,而是由getMethod()引起。需要实际声明的类才能在类中找到方法。但在调用方法时,可以传递任何子类实例。几乎每次使用反射时都不应该这样做。可能有比反射更好的方法来实现你想要的目标。你想要实现什么? - JB Nizet
是的,异常是由getMethod()引起的,也许我表达不够清楚。我使用了这个MVC实现。在这个实现中,控制器使用invoke来告诉模型视图中发生了什么变化。 - Andre Hofmeister
3个回答

3
你需要询问它的确切类型。这是因为你可以有多个可能的重载方法,需要知道你想要的确切方法。

所以你可以使用子类调用方法,但是你无法在没有它的情况下请求一个子类。

你可以查看所有方法并找到匹配项。

如果你只需要属性的setter或getter,则建议你查看BeanIntrospector,它将为你找到所有属性及其setter/getter方法。


问题在于我不知道哪个问题被添加到模型中。它可能是ProblemX,ProblemY或ProblemZ。 - Andre Hofmeister
@hofmeister,您不需要知道它是哪种实例类型,您只需要知道该方法的类型。 - Peter Lawrey
是的,你说得对。ProblemX实例化Problem应该足以为getMethod()设置正确的参数了吧? - Andre Hofmeister
2
调用setNewProblem(Problem)对于Problem的任何子类来说已经足够了。您确定需要反射吗? - Peter Lawrey
1
可能这是最好的解决方案。改变MVC并且抛弃反射。 - Andre Hofmeister
@hofmeister 使用反射会带来许多问题,如果可以的话最好避免使用。 - Peter Lawrey

1
问题在于newValue.getClass()是已声明方法中的类的子类。
Class.getMethod

要在类C中找到匹配的方法:如果C正好声明了一个具有指定名称和完全相同形式参数类型的公共方法,则反映出该方法。

你可以一直往上遍历继承链,直到它可用为止。
Method getMethod(Class c1, Class c2) {
    if(c2.getSuperClass() == null) {
        return c1.getMethod("set" + propertyName, new Class[] { c2 });
    }
    try {
        return c1.getMethod("set" + propertyName, new Class[] { c2 });
    } catch(NoSuchMethodException e) {
        return getMethod(c1, c2.getSuperClass());
    }
}

使用方法:

Method method = getMethod(model.getClass(), newValue.getClass());

我有些犹豫地建议这样做,因为它并不能覆盖所有情况(比如形式参数类是接口的情况),而且你现在这么做是不好的。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接