16

写类似的东西时

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在这方面有点复杂。


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

正如答案中所建议的那样,BeanUtils.invokeMethod接近了。它应该找到最好的匹配,不管它意味着什么。查看MethodUtils.getMatchingAccessibleMethod表明

  • 它对可变参数一无所知
  • 这是不确定的

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

4

2 回答 2

1

或者,您可以使用Apache Commons 的 Bean Utils

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

根据文件

返回具有给定名称和参数的可访问方法(即可以通过反射调用的方法)。如果找不到这样的方法,则返回 null。这只是 getAccessibleMethod(Method 方法) 的一个方便的包装器。

参数: 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,然后调用它。

于 2012-08-01T19:09:19.683 回答
0

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
于 2012-08-01T19:14:18.680 回答