如何在Java中找到重载方法?

时间:2012-08-01 18:51:22

标签: java reflection overloading

撰写类似

的内容时
doit(43, 44, "hello");

编译器知道要调用哪个重载方法。当我想通过反思做同样的事情时,我需要找出自己,方法是

doit(Integer, double, CharSequence...);

并通过类似

的方式获取
Class[] types = {Integer.class, double.class, CharSequence[].class};
declaringClass.getDeclaredMethod("doit", types);

我想知道是否已经允许我写一些东西了

Method m = getMethod(declaringClass, "doit", 43, 44, "hello");

我想知道是否有人这样做了,因为JLS在这方面有点复杂。


实际上,像Phase 1这样的完全的行为是不可能的,因为编译器只接受匹配而没有装箱和拆箱的方法。当从上面调用我假设的getMethod时,基元和它们的包装器之间的区别已经丢失(因为通过varargs传递参数时的自动装箱)。这个问题似乎没有解决方案,所以让我们忽略它。

正如答案所示,BeanUtils.invokeMethod接近尾声。它应该找到最佳匹配,无论它意味着什么。查看MethodUtils .getMatchingAccessibleMethod表示

  • 它对varargs一无所知
  • 这是非确定性的

所以我正在寻找更好的东西。

2 个答案:

答案 0 :(得分:2)

MethodHandle是使用签名获取重载方法的新方法(java 7):

示例:

static class A {
    public String get() {
        return "A";
    }
}

static class B extends A {
    public String get() {
        return "B";
    }
}

public static void main(String[] args) throws Throwable {

    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodType mt = MethodType.methodType(String.class);
    MethodHandle mh = lookup.findVirtual(A.class, "get", mt);;

    System.out.println(mh.invoke(new B()));
}

输出:

B

答案 1 :(得分:1)

或者您可以使用Bean Utils from Apache Commons

public static Method getAccessibleMethod(
        Class clazz,
        String methodName,
        Class[] parameterTypes)

根据documentation

  

返回一个可访问的方法(也就是说,可以通过   具有给定名称和参数的反射)。如果没有这样的方法可以   发现,返回null。这只是一个方便的包装   getAccessibleMethod(方法方法)。

     

参数:    clazz - 从此课程中获取方法    methodName - 使用此名称获取方法    parameterTypes - 使用这些参数类型

实现获取可访问的方法并在层次结构中上升,直到找到匹配为止。

指向调用

为了直接按照您的要求执行调用,您可以使用同一API中的此方法:

public static Object invokeExactMethod(
        Object object,
        String methodName,
        Object[] args,
        Class[] parameterTypes)
        throws
        NoSuchMethodException,
        IllegalAccessException,
        InvocationTargetException

甚至

public static Object invokeExactMethod(
        Object object,
        String methodName,
        Object[] args)
        throws
        NoSuchMethodException,
        IllegalAccessException,
        InvocationTargetException

首先使用getAccessibleMethod定位方法,稍后再调用它。