2016-06-08 5 views
0

Предположим, что у вас есть MethodHandle и указаны некоторые аргументы, как изменить эти аргументы после их установки?Как изменить аргументы MethodHandle после вставки?

import static java.lang.invoke.MethodType.*; 
import static java.lang.invoke.MethodHandles.*; 

import java.lang.invoke.MethodHandle; 
import java.lang.invoke.MethodHandles; 

public class SomeTest { 

    public static void main(String[] args) throws Throwable { 

     MethodHandle methodHandle = MethodHandles.lookup().findVirtual(SomeTest.class, 
       "someMethod", methodType(void.class, String.class)); 

     methodHandle = MethodHandles.insertArguments(methodHandle, 1, "Hi"); 

     // this invoke calls with "Hi", which is fine 
     methodHandle.invoke(new SomeTest()); 

     // here, how to change the arguments to be e.g. "Hello" instead of "Hi" 

     methodHandle.invoke(new SomeTest()); 

    } 

    public void someMethod(String a) { 
     System.out.println("Called with " + a); 
    } 
} 

Я попытался использовать MethodHandles. filterArguments()

.... 
    methodHandle = MethodHandles.filterArguments(methodHandle, 1, 
      MethodHandles.lookup().findStatic(SomeTest.class, "returnSomething", 
        methodType(String.class))); 

    methodHandle.invoke(new SomeTest()); 
} 

public static String returnSomething() { 
    return "Hello"; 
} 

, но я получаю исключение:

Exception in thread "main" java.lang.IllegalArgumentException: too many filters 
    at java.lang.invoke.MethodHandleStatics.newIllegalArgumentException(MethodHandleStatics.java:139) 
    at java.lang.invoke.MethodHandles.filterArgumentsCheckArity(MethodHandles.java:2623) 
    at java.lang.invoke.MethodHandles.filterArguments(MethodHandles.java:2595) 
    at test.test.SomeTest.main(SomeTest.java:22) 
+2

Метод ручка неизменна и * Инкапсуляция * поведение. Невозможно изменить значение привязки. Если вы хотите связать разные значения, сохраните дескриптор исходного метода, который имеет этот параметр. – Holger

ответ

0

2 методы:

  • Повторное использование исходный дескриптор метода и привязать его к другой строке:

    MethodHandle methodHandle = MethodHandles.lookup().findVirtual(SomeTest.class, 
         "someMethod", methodType(void.class, String.class)); 
    MethodHandle hi = methodHandle.insertArguments(1, "Hi"); 
    MethodHandle hello = methodHandle.insertArguments(1, "Hello"); 
    hi.invoke(new SomeTest()); // "Hi" 
    hello.invoke(new SomeTest()); // "Hello" 
    
  • Bi nd второй аргумент для getter члена класса, которым вы управляете. Вы должны отфильтровать аргументы с помощью «exactInvoker», который будет выполнять getter, чтобы получить значение String. См:

    public static class StringHolder{ 
        public String toPrint; 
        StringHolder(String toPrint){ 
         this.toPrint = toPrint; 
        } 
    } 
    
    public static void main(String[] args) throws Throwable { 
        MethodHandle toPrintGetter = lookup().findGetter(StringHolder.class, "toPrint", String.class); 
        MethodHandle someMethod = lookup().findVirtual(SomeTest.class, "someMethod", MethodType.methodType(void.class, String.class)); 
    
        StringHolder holder = new StringHolder("Hi"); 
        someMethod = MethodHandles.filterArguments(someMethod, 1, MethodHandles.exactInvoker(MethodType.methodType(String.class))); 
        MethodHandle stringPrinter = MethodHandles.insertArguments(someMethod, 1, toPrintGetter.bindTo(holder)); 
    
        stringPrinter.invokeExact(new SomeTest()); // prints "Hi" 
        holder.toPrint = "Hello"; 
        stringPrinter.invokeExact(new SomeTest()); // prints "Hello" 
    } 
    
+0

Спасибо, но я получаю «Исключение в потоке» main «java.lang.IllegalArgumentException: типы целей и фильтров не совпадают: (SomeTest, String) void, (MethodHandle) String' –

+0

Да, опечатка на моей стороне, индекс для filterArguments должно быть 1 вместо 0. – Gui13

+0

Спасибо, но ответ изменяет дескриптор метода до первого вызова. Пожалуйста, проверьте мой опубликованный код, мне нужно изменить методHandle после того, как был установлен аргумент. –