#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 возвращают корректные значения (в любом более сложном случае будут возвращаться имена анонимных классов/методов).
Комментариев нет:
Отправить комментарий