假设我有以下方法:
void test () {...}
我通过反射得到这个方法,但是调用它会非常慢,所以我想从中获取Runnable,好像我会写一样
this::test
有没有办法实现这个目标?
答案 0 :(得分:1)
我需要一个像这样的方法的实现:
Runnable toRunnable(Method method);
所以我们得到一个Method
,我们需要返回Runnable
这与this::test
不完全相同,因为它也使用this
实例进行绑定,因此您还必须传递要绑定的实例。但是,您可以使用方法句柄,这是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
需要在与您尝试访问的方法相同的模块中创建。 (简而言之,方法句柄对它有一些访问限制)。但是,如果您尝试访问的方法和类可以公开访问,那么就没有问题了。