[英]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.