【问题标题】:Java reflection where a method parameter is an interface方法参数是接口的 Java 反射
【发布时间】:2011-04-03 06:49:30
【问题描述】:

首先让我说我正在维护别人设计不佳的代码,所以我可以更改它的数量有限。

现在发生的事情是,他们创建了一系列由反射调用的方法。其中一种方法将 Map 作为其参数之一。在运行时,此 Map 使用 Hashtable 实现。

这就是问题所在 - 我得到一个 NoSuchMethodException ,因为它正在寻找一个以 Hashtable 作为参数的方法,即使 Hashtable 实现了 Map 接口。让我感到困惑的是,如果我不使用反射(在这种情况下是一项重大的设计更改)并传递了一个 Hashtable 它将调用带有 Map 参数的方法 - 那么为什么当我使用反射时它的工作方式不同?

鉴于我几乎必须坚持使用反射,有没有办法让带有 Map 参数的方法在我传递一个实现该接口的类时被调用?

如果你愿意,我可以模拟一些代码来演示......

【问题讨论】:

    标签: java reflection interface


    【解决方案1】:

    如果使用java.lang.Class 中的getMethod(String name, Class[] parameterTypes),则需要指定接口方法签名中表示的参数类型(静态类型),而不是运行时对象的类型(动态类型)。

    所以,对于methodXyz(Map map),而不是:

    Method m = cl.getMethod("methodXyz", new Class[]{argument.getClass()});
    

    这样做:

    Method m = cl.getMethod("methodXyz", new Class[]{Map.class});
    

    【讨论】:

    • 问题是大约有 20 种称为 methodXyz 的方法,其各种参数都可以正常工作。只有这个新的将 Map 作为导致问题的参数。我可以按照您说的做,但这要求我首先使用 instanceof 确定所讨论的参数是否是 Map :) 我不明白为什么在查找方法时反射的操作方式与非反射代码的操作方式不同? !?!我猜它必须使用完全不同的机制......
    • getMethod() 需要定义的确切类型。这就是为什么它被命名为 getMethod() 而不是 findMethod()。如果您经常进行动态方法分派,您可以编写自己的 findMethod() 代码。这将涉及寻找具有正确名称的方法,过滤参数与给定参数不兼容的方法,并处理多个方法仍然候选的情况,例如以下情况不明确,是编译错误:new StringBuffer().append(null).
    【解决方案2】:

    我遇到了类似的问题。我看到了 2 个解决方案:

    解决方案 1:您可以开发一种更复杂的搜索方法。

    您可以使用的算法示例:

    您使用参数类型进行搜索。如果搜索失败(异常),但其中一个参数具有超类型(或实现接口),则搜索相同的方法名称,但使用此超类(或接口)。 只有在此搜索算法之后没有找到任何方法时,才会抛出异常。

    注意:如果您的方法有多个参数,请务必使用超类型/接口的每种可能组合进行验证。它会导致一个相当复杂的搜索算法......

    解决方案 2: 另一种更简单的方法是将类型与参数分开来精确。如果要使用空参数,则可能需要此方法更详细。

    所以,“invokeMethod(String methodName, Object[] paramters)”变成了“invokeMethod(String methodName, Class[] methodParamTypes, Object[] parameters )"。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-25
      • 2012-11-16
      • 2011-06-21
      • 2011-04-16
      • 1970-01-01
      • 1970-01-01
      • 2016-06-16
      • 2011-04-05
      相关资源
      最近更新 更多