Пример MethodHandle генерирует исключение WrongMethodTypeException при вызове invokeExact - PullRequest
5 голосов
/ 10 января 2012

Пример, показанный в описании класса MethodHandle, вызывает WrongMethodTypeException при вызове оператора mh.invokeExact("daddy",'d','n') со следующим описанием: (CC)Ljava/lang/String; cannot be called with a different arity as ([Ljava/lang/Object;)Ljava/lang/Object;.

Объект MethodHandle mh имеет дескриптор символьного типа, соответствующий: (CC)Ljava/lang/String. Но когда мы вызываем mh.invokeExact("daddy",'d','n'), аргументы: d и n передаются как массив Object, а затем они не совпадают с аргументами типа char.

Я знаю, что могу решить вышеуказанную проблему, используя invokeWithArguments вместо invokeExcat или invoke, но этот пример должен был работать, как представлено в описании MethodHandle Java 7 API , Кроме того, invokeWithArguments имеет снижение производительности по отношению к invoke / invokeExact.

Ответы [ 2 ]

2 голосов
/ 11 января 2012

Как вы это компилируете?

Для меня это звучит подозрительно, как известная ошибка Eclipse.

Я только что проверил с помощью javac, и этот код:

import java.lang.invoke.*;

public class ScratchMH {    
        private static ScratchMH instance = null;

        public ScratchMH() {
                super();
        }

        private void run() throws Throwable {
                Object x, y; String s; int i;
                MethodType mt; MethodHandle mh;
                MethodHandles.Lookup lookup = MethodHandles.lookup();

                // mt is (char,char)String
                mt = MethodType.methodType(String.class, char.class, char.class);
                mh = lookup.findVirtual(String.class, "replace", mt);
                s = (String) mh.invokeExact("daddy",'d','n');
                // invokeExact(Ljava/lang/String;CC)Ljava/lang/String;

                System.out.println(s);
        }

        public static void main(String[] args) throws Throwable {
                instance = new ScratchMH();
                instance.run();
        }
}

, кажется, работает нормально:

ariel-2:src boxcat$ javac scratch/clj/ScratchMH.java 
ariel-2:src boxcat$ java scratch/clj/ScratchMH
nanny
ariel-2:src boxcat$ 

Соответствующая часть вывода из javap также кажется разумной:

  35: invokevirtual #8                  // Method java/lang/invoke/MethodHandles$Lookup.findVirtual:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;
  38: astore        6
  40: aload         6
  42: ldc           #9                  // String daddy
  44: bipush        100
  46: bipush        110
  48: invokevirtual #10                 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/String;CC)Ljava/lang/String;
  51: astore_3      
0 голосов
/ 11 августа 2016

invokeExact требует точного соответствия между описанием типа метода MH и типами аргументов. Так как тип метода MH (cc)string, то, что вы хотите выполнить MH, и первый, и второй аргументы должны быть char. Таким образом, это так

``String s = (String)mh.invokeExact('a', 'b')``
...