[英]How to call MethodHandle.invokeExact() with an array of Object[]?
Java's MethodHandle.invokeExact(Object...args) takes a variable-length list of arguments. Java的MethodHandle.invokeExact(Object ... args)采用可变长度的参数列表。 When I try to pass an array of Object [] instead of a list, though, I get an error. 但是,当我尝试传递Object []而不是列表数组时,我收到错误。 See below: 见下文:
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);
}
}
The second call to invokeExact() produces this Exception: 第二次调用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)
This might be related to a bug in Eclipse that was fixed two years ago ( https://bugs.eclipse.org/bugs/show_bug.cgi?id=385404 ) but I don't think so, because when I close Eclipse, delete the /target directory, recompile everything using Maven, and run from the command line I get the same results. 这可能与两年前修复的Eclipse中的错误有关( https://bugs.eclipse.org/bugs/show_bug.cgi?id=385404 ),但我不这么认为,因为当我关闭Eclipse时,删除/ target目录,使用Maven重新编译所有内容,并从命令行运行,我得到相同的结果。
I'm using Eclipse Kepler SR2, everything fully up to date, and JDK 1.7.0_25. 我正在使用Eclipse Kepler SR2,一切都是最新的,JDK 1.7.0_25。
MethodHandle.invoke()
and MethodHandle.invokeExact()
are special methods that don't behave like other variable arity methods: MethodHandle.invoke()
和MethodHandle.invokeExact()
是不像其他变量arity方法那样运行的特殊方法:
As is usual with virtual methods, source-level calls to
invokeExact
andinvoke
compile to aninvokevirtual
instruction. 由于是用常用的虚拟方法,源级调用invokeExact
和invoke
编译为一个invokevirtual
指令。 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. 然后,编译器使用符号类型描述符调用方法句柄,该描述符描述参数和返回类型。
So, types of parameters really matter when you call these methods. 因此,当您调用这些方法时,参数类型真的很重要。 If you want to pass parameters as Object[]
, you should use invokeWithArguments()
instead: 如果要将参数作为Object[]
传递,则应使用invokeWithArguments()
代替:
mh.invokeWithArguments(myArray);
See also: 也可以看看:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.