如何用Object []数组调用MethodHandle.invokeExact()? [英] How to call MethodHandle.invokeExact() with an array of Object[]?

查看:113
本文介绍了如何用Object []数组调用MethodHandle.invokeExact()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java的MethodHandle.invokeExact(Object ... args)采用可变长度的参数列表.但是,当我尝试传递Object []数组而不是列表时,出现错误.见下文:

Java's MethodHandle.invokeExact(Object...args) takes a variable-length list of arguments. When I try to pass an array of Object [] instead of a list, though, I get an error. 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);
    }
}

第二次调用invokeExact()会产生此异常:

The second call to invokeExact() produces this Exception:

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重新编译所有内容,然后从命令行运行我得到相同的结果.

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 Kepler SR2,所有内容都是最新的,以及JDK 1.7.0_25.

I'm using Eclipse Kepler SR2, everything fully up to date, and JDK 1.7.0_25.

推荐答案

MethodHandle.invoke()MethodHandle.invokeExact()是特殊方法,其行为与其他可变arity方法不同:

MethodHandle.invoke() and MethodHandle.invokeExact() are special methods that don't behave like other variable arity methods:

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

As is usual with virtual methods, source-level calls to invokeExact and invoke compile to an invokevirtual 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():

So, types of parameters really matter when you call these methods. If you want to pass parameters as Object[], you should use invokeWithArguments() instead:

mh.invokeWithArguments(myArray);

另请参见:

  • MethodHandle javadoc

这篇关于如何用Object []数组调用MethodHandle.invokeExact()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆