【问题标题】:Call getMethod with a subclass as method argument使用子类作为方法参数调用 getMethod
【发布时间】:2013-11-30 11:52:13
【问题描述】:

是否可以调用参数对象或参数类是子类的方法,并且方法本身将超类作为参数?

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

我这样调用调用:

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

如果我将 newValue.getClass() 更改为 Problem.class 一切正常。知道如何将子类传递给public void setNewProblem(Problem problem);

【问题讨论】:

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

标签: java reflection subclass invoke superclass


【解决方案1】:

当您调用Class.getMethod() 时,您必须正确指定正式 参数类型。不是您计划提供的实际参数的类型。您必须准确匹配相关方法声明中的内容。

"The parameterTypes parameter is an array of Class objects that identify the method's formal parameter types, in declared order."

【讨论】:

    【解决方案2】:

    您必须询问它的确切类型。这是因为您可以有多种可能的重载方法,并且它需要确切地知道您想要什么。

    所以你可以调用一个子类,但你不能在没有子类的情况下请求一个子类。

    您可以做的是查看所有方法并找到匹配项。

    如果您只需要某个属性的 setter 或 getter,我建议您查看 BeanIntrospector,它会为您找到该属性的所有属性和 getter/setter 方法。

    【讨论】:

    • 问题是不知道,是哪个问题加到模型上的。可能是 ProblemX、ProblemY 或 ProblemZ。
    • @hofmeister 你不需要知道它是哪个实例类型,你只需要知道方法的类型。
    • 是的,你的权利。 ProblemX 的 Problem 实例应该足以为 getMethod() 设置正确的参数?
    • 调用 setNewProblem(Problem) 对于任何问题的子类都足够了。你确定你需要反思吗?
    • 这可能是最好的解决方案。更改 MVC 并丢弃反射。
    【解决方案3】:

    问题是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());
    

    但是,我不愿建议这样做,因为它没有涵盖 100% 的情况(例如,如果形式参数类是接口),而且您这样做的方式很糟糕。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 2021-05-05
      相关资源
      最近更新 更多