Страницы

Поиск по вопросам

понедельник, 6 января 2020 г.

Как определить какая реализация в лямбда-выражении до его исполнения?

#java #лямбда_выражение


Постигаю лямбда-выражения и возник вопрос: «возможно ли определить какая реализация
в момент времени в лямбда-выражении?»
Пример ниже:

interface TestLambda{
    String exec();
}

public class Main {

    public static String meth1(){return "1";}
    public static String meth2(){return "2";}

    public static void main(String[] args) {

        TestLambda l = ((new Random()).nextBoolean())?(Main::meth1):(Main::meth2);
        /* как определить что сейчас в переменой l, т.е. что выполниться при l.exec()  */
        System.out.println(l.exec());

    }
}

    


Ответы

Ответ 1



В комментариях уже написали, что определение реализации интерфейса, тем более лямбда-выражения, противоречит назначению как интерфейсов, так и лямбда выражений. Наверняка задачу для которой потребовался подобный механизм можно решить изменением логики, например: отделить логику определения нужного метода от вызова; вместо лямбда выражений генерировать объекты классов с заданным интерфейсом; оборачивать используемые классы добавляя по мере необходимости идентификацию и вывод в логи. Тем не менее, если будут использоваться только ссылки на методы, то может подойти решение ниже: Если сделать интерфейс сериализуемым: interface TestLambda extends Serializable { String exec(); } , то будет работать такой метод: private static String findMethodName(TestLambda setter) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Class cl = setter.getClass(); Method m = cl.getDeclaredMethod("writeReplace"); m.setAccessible(true); Object replacement = m.invoke(setter); SerializedLambda l = (SerializedLambda) replacement; return l.getImplClass() + "::" + l.getImplMethodName(); } И он будет возвращать названия методов и классов: TestLambda lambda = new Random().nextBoolean() ? Main::meth1 : Main::meth2; System.out.println(findMethodName(lambda)); Работа метода основана на том, что: если целевой тип лямбды сериализуем, то и лямбда сериализуема; для сериализации лямбды создается анонимный тип, в котором определяется метод writeReplace, который возвращает SerializedLambda; используется ссылка на метод и сигнатуры полностью совпадают, вследствие чего getImplClass и getImplMethodName возвращают корректные значения (в любом более сложном случае будут возвращаться имена анонимных классов/методов).

Комментариев нет:

Отправить комментарий