假设我有以下方法:
void test () {...}
我通过反射获取这个方法,但是调用它会非常慢,所以我想从中获取Runnable,就像我会写一样
this::test
有什么办法可以实现这一点吗?
最佳答案
I need an implementation for method like this:
Runnable toRunnable(Method method);
So we are getting aMethod
and we need to returnRunnable
这并不完全等同于 this::test
,因为它也使用 this
要绑定(bind)到的实例,因此您还必须传递要绑定(bind)到的实例。但是,您可以使用方法句柄,这是类似 this::test
的底层实现。 .
像这样的类:
public class MyClass {
public void test() {
System.out.println("Test Called");
}
}
您可以创建此方法:
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
public static Runnable toRunnable(Method method, Object instance) throws ReflectiveOperationException {
Lookup lookup = lookup();
MethodHandle test = lookup.unreflect(method);
try {
return (Runnable) LambdaMetafactory.metafactory(
lookup,
"run",
methodType(Runnable.class, instance.getClass()),
methodType(void.class),
test,
methodType(void.class)
).getTarget().invoke(instance);
} catch (Throwable e) {
throw new RuntimeException("Should not occur", e);
}
}
并这样调用它:
Object ref = new MyClass(); // get from somewhere
Runnable result = toRunnable(ref.getClass().getMethod("test"), ref);
result.run(); // prints 'Test Called'
需要注意的是 test
方法必须可以从您调用 lookup()
的位置访问,您可以通过传递 Lookup
来解决这个问题手动添加到该方法,并在可以访问 test
的位置创建它方法。或者,如果您使用的是 Java 9,则可以使用 privateLookup(Class<?>, Lookup)
相反,但是 Lookup
您传递给的需要在与您尝试访问的方法相同的模块中创建。 (简而言之,方法句柄有更多的访问限制)。但如果您尝试访问的方法和类可以公开访问,那么就没有问题。
关于java - 如何从 Java 方法获取 lambda 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50430182/