【问题标题】:Java: runtime method resolutionJava:运行时方法解析
【发布时间】:2011-05-16 17:34:00
【问题描述】:

我正在通过解释器进行一些动态代码调用,并且我正在进入 JLS section 15.12 中讨论的方法解析的棘手难看领域。

选择方法的“简单”方式是当您知道所有参数的确切类型时,您可以使用Class.getDeclaredMethod(String name, Class[] parameterTypes)。也许你必须检查方法的可访问性和类的超类/超接口。

但这不包括以下任何一种情况,所以它有点没用:

  • 装箱/拆箱基元
  • 子类型
  • 可变参数
  • null 参数(可以是任何类型,除非解释器另有说明;在编译时,可以通过将 null 转换为类/接口来消除任何歧义)
  • 原始类型转换(不是 Java 的一部分,但在语言上下文中是允许的 - 例如 Rhino Javascript,其中所有数字都是浮点数,因此 Java 代码可能采用 int 但调用者传入一个数字是 intdouble)

(请参阅下面的前三个示例)

所以现在我必须编写自己的方法解析库...

是否有任何知名的框架库可以帮助解决这个问题?

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);
    }
}

【问题讨论】:

  • @Jonathon:我知道 isAssignableFrom。我得到了一些使用子类型和装箱/拆箱的本土产品。然后我开始使用可变参数,它变得很糟糕,我想,“等一下,我为什么要这样做?”所以我专门寻找一个预先存在的图书馆。 (或者至少是一组很好的预先存在的测试用例)否则我可以自己做,但这是一个很大的痛苦。
  • 除非你找到一个可爱的图书馆,否则我认为你所做的一切都会变得丑陋且难以阅读。
  • 是的,我知道。如何吸引 Google、Oracle、IBM 或 Apache 或其他任何地方的 Java 半神来制作一个好的非病毒开源库来做到这一点?恕我直言,这是Java反射的缺失部分。我可以想出一些适合我自己目的的东西,但我认为它远非完美,无论是正确性/文档/可维护性。

标签: java reflection overload-resolution


【解决方案1】:

您可能想阅读this blog post 并查看ClassMate。它应该为您完成大部分蹩脚的工作。

【讨论】:

  • 啊!很有希望,但它略有不同——它解析泛型类型,但对方法解析没有任何作用。但至少这是一个开始,我敢打赌我可以说服作者扩展它。
【解决方案2】:

Commons beanutils 有这个查找匹配方法的功能: getMatchingAccessibleMethod

它适用于原始类型,但正如文档所说,它有点不确定。

【讨论】:

  • 请注意,在getMatchingAccessibleMethod 中,原始匹配是一种方式 - 参数Long.class 将匹配foo(long)Long.TYPE 不会匹配foo(Long)
  • +1: @Bengt: 发现 Apache 有一些工具真是一种解脱,也许不是我想要的,但至少是一些东西。
【解决方案3】:

guava-discuss 上的一位用户推荐我查看Mirror library

不幸的是,它也不处理重载决议,至少目前没有。

【讨论】:

    【解决方案4】:

    我在 MVEL 和属性方面取得了一些成功,但我不记得它是否可以调度方法调用。

    但是,您可能正在寻找完全不同的语言。鉴于问题的性质,我建议看看 Groovy,它与 Java 的集成非常干净。

    【讨论】:

    • 嗯,由于各种原因,我“卡”在 Java 上,最大的原因是可维护性(添加不同的语言会严重限制我从其他开发人员那里获得帮助的能力)
    猜你喜欢
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多