Java 的 MethodHandle.invokeExact(Object...args) 采用可变长度的参数列表。但是,当我尝试传递 Object [] 数组而不是列表时,出现错误。见下文:
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 错误 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=385404) 有关,但我不这么认为,因为当我关闭 Eclipse 时,删除/target 目录,使用 Maven 重新编译所有内容,然后运行从命令行我得到了相同的结果。
我正在使用 Eclipse Kepler SR2,一切都是最新的,还有 JDK 1.7.0_25。
最佳答案
MethodHandle.invoke()
和 MethodHandle.invokeExact()
是特殊方法,其行为与其他变量方法不同:
As is usual with virtual methods, source-level calls to
invokeExact
andinvoke
compile to aninvokevirtual
instruction. More unusually, the compiler must record the actual argument types, and may not perform method invocation conversions on the arguments. Instead, it must push them on the stack according to their own unconverted types. The method handle object itself is pushed on the stack before the arguments. The compiler then calls the method handle with a symbolic type descriptor which describes the argument and return types.
因此,当您调用这些方法时,参数的类型非常重要。如果您想将参数作为 Object[]
传递,您应该改用 invokeWithArguments()
:
mh.invokeWithArguments(myArray);
另请参阅:
关于java - 如何使用 Object[] 数组调用 MethodHandle.invokeExact()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23434259/