Мне нужна реализация для метода, подобного этому: 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
, который вы передаете этому, должен быть создан в том же модуле, что и метод, к которому вы пытаетесь получить доступ.(короче говоря, у дескрипторов методов есть еще несколько ограничений доступа).Но если метод и класс, к которому вы пытаетесь получить доступ, являются общедоступными, тогда проблем нет.