Как надежно получить экземпляр объекта для ссылки на метод - PullRequest
0 голосов
/ 26 октября 2019

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