Как звонить из MethodHandle.invokeExact() с массивом Object[]?

MethodHandle Java.invokeExact(объект...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.

1 ответов


MethodHandle.invoke() и MethodHandle.invokeExact() специальные методы, которые не ведут себя как другие методы переменной arity:

как обычно с виртуальными методами, вызовы исходного уровня на invokeExact и invoke компиляции к invokevirtual инструкция. Более необычно, компилятор должен записывать фактические типы аргументов и не может выполнять преобразования вызова метода для Аргументов. Вместо этого он должен толкать их в стек в соответствии с их собственными необращенными типами. Метод сам объект handle помещается в стек перед аргументами. Затем компилятор вызывает дескриптор метода с символьным дескриптором типа, который описывает типы аргументов и возвращаемых значений.

Итак, типы параметров действительно имеют значение, когда вы вызываете эти методы. Если вы хотите передать параметры как Object[], вы должны использовать invokeWithArguments() вместо:

mh.invokeWithArguments(myArray);

Читайте также: