Java 如何使用对象[]数组调用MethodHandle.invokeExact()?

Java 如何使用对象[]数组调用MethodHandle.invokeExact()?,java,eclipse,reflection,invokedynamic,methodhandle,Java,Eclipse,Reflection,Invokedynamic,Methodhandle,Java的MethodHandle.invokeExact(Object…args)接受长度可变的参数列表。但是,当我试图传递对象[]的数组而不是列表时,我得到了一个错误。见下文: private void doIt() throws Throwable { Method meth = Foo.class.getDeclaredMethods()[0]; MethodHandles.Lookup lookup = MethodHandles.lookup(); Met

Java的MethodHandle.invokeExact(Object…args)接受长度可变的参数列表。但是,当我试图传递对象[]的数组而不是列表时,我得到了一个错误。见下文:

private void doIt() throws Throwable {

    Method meth = Foo.class.getDeclaredMethods()[0];

    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodHandle mh = lookup.unreflect(meth);

    Foo foo = new Foo();
    String myStr = "aaa";
    Integer myInt = new Integer(10);
    Object [] myArray = {foo, myStr, myInt};

    mh.invokeExact(foo, myStr, myInt); // prints "Called aaa 10"
    mh.invokeExact(myArray); // throws Exception
}

class Foo {
    public void bar(String myStr, Integer myInt) {
        System.out.println("Called " + myStr + " " + myInt);
    }
}
对invokeExact()的第二次调用产生以下异常:

Exception in thread "main" java.lang.invoke.WrongMethodTypeException: (Ljava/lang/String;Ljava/lang/Integer;)V cannot be called with a different arity as ([Ljava/lang/Object;)V
    at io.rhubarb.core.TestInvoke.doIt0(TestInvoke.java:26)
    at io.rhubarb.core.TestInvoke.main(TestInvoke.java:11)
这可能与两年前修复的Eclipse中的一个bug()有关,但我不这么认为,因为当我关闭Eclipse、删除/target目录、使用Maven重新编译所有内容并从命令行运行时,我会得到相同的结果

我使用的是Eclipse开普勒SR2,所有内容都是最新的,JDK 1.7.0_25。

MethodHandle.invoke()
MethodHandle.invokeExact()
是一种特殊的方法,它们的行为与其他变量arity方法不同:

与虚拟方法一样,对
invokeExact
invoke
的源代码级调用编译为
invokevirtual
指令。更不寻常的是,编译器必须记录实际的参数类型,并且不能对参数执行方法调用转换。相反,它必须根据它们自己未转换的类型将它们推送到堆栈上。方法句柄对象本身在参数之前被推送到堆栈上。然后,编译器使用描述参数和返回类型的符号类型描述符调用方法句柄

因此,当您调用这些方法时,参数的类型确实很重要。如果要将参数作为
Object[]
传递,应改用
invokeWithArguments()

mh.invokeWithArguments(myArray);
另请参见:


首先为什么要使用反射?在这种情况下,我会说InvokeExact方法签名非常容易误导。为什么要将其作为对象公开。。。而不是某个可以公开“addParam”方法的构建器类?是的,这是crazytown!