简体   繁体   English

插入后如何更改MethodHandle参数?

[英]How to change MethodHandle arguments after being inserted?

Suppose you have MethodHandle and some arguments have been specified, how to change those arguments after being set? 假设您有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);
    }
}

I have tried to use MethodHandles. 我试图使用MethodHandles。 filterArguments() 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";
}

but I get an exception: 但我有一个例外:

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 methods: 2种方法:

  • Reuse your original method handle and bind it to another string: 重用原始方法句柄并将其绑定到另一个字符串:

     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" 
  • Bind the second argument to a getter of a class member, which you manipulate. 将第二个参数绑定到您要操纵的类成员的getter上。 You have to filter the arguments with an "exactInvoker" that will perform the getter to actually get the String value. 您必须使用“ exactInvoker”过滤参数,该参数将执行getter来实际获取String值。 See: 看到:

     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" } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM