Я пытаюсь изучить, как я могу получить экземпляр объекта из ссылки на метод, которая указывает на существующий объект, и я не уверен, какой будет надежный метод для его получения, чтобы он работал для всех реализаций JVM.
Подход, который я нашел, который, по крайней мере, работал для JVM Oracle, заключается в том, что создается впечатление, что частное поле arg $ 1 генерируется как часть объекта methodReference, и к нему можно обратиться с помощью самоанализа.
Таким образом, данный класс имеет следующий класс:
public class SomeClass {
public void doSomething(List<String> a) {
a.forEach(o -> {System.out.println(o);});
}
}
Метод юнит-теста:
SomeClass instance = new SomeClass();
Consumer<List<String>> consumer = instance::doSomething;
Field[] fields = consumer.getClass().getDeclaredFields();
Field field = consumer.getClass().getDeclaredField("arg$1");
field.setAccessible(true);
Object myInstance = field.get(consumer);
assertThat(instance).isSameAs(myInstance);
Так кто-нибудь знает, является ли это наиболее подходящим подходом или существует лучший и более надежный подход?
Заранее спасибо
Изменить более полный пример можно следующим образом:
Прокси-класс, который будет выступать в качестве прокси для реального экземпляра:
public class Proxy {
public Consumer<List<String>> delegate;
public void work(List<String> strings) {
if (delegate != null) {
delegate.accept(strings);
}
}
}
Рабочий, который собирается выполнять работу:
public class Worker {
public final Consumer<List<String>> work;
public Worker(Consumer<List<String>> work) {
this.work = work;
}
public void execute() {
work.accept(Lists.newArrayList("A", "B"));
}
}
Тестовый случай, когда вводится какое-то другое поведение:
public class Test {
public void injectNewBehaviorIntoProxy(Worker worker) throws NoSuchFieldException, IllegalAccessException {
Consumer<List<String>> work = worker.work;
// at a later stage in gradle where delegator is not known
Field[] fields = work.getClass().getDeclaredFields();
Field field = work.getClass().getDeclaredField("arg$1");
field.setAccessible(true);
Object myInstance = field.get(work);
Proxy proxy = (Proxy) myInstance;
proxy.delegate = strings -> {
System.out.println(String.format("Got: %s", strings.toString()));
};
}
@org.junit.Test
public void get_instance() throws NoSuchFieldException, IllegalAccessException {
Proxy proxy = new Proxy();
Worker worker = new Worker(proxy::work);
injectNewBehaviorIntoProxy(worker);
worker.execute();
}
}