Я столкнулся с проблемой — как получить из method reference вида вызываемый метод класса (или хотя бы его имя), т.е. в примере это java.lang.String.length(). Как выяснилось, не одного меня волновал этот вопрос, нашлись такие обсуждения на stackoverflow , , проекты на GitHub, которые так или иначе касаются этой проблемы , , , но не один из них не дает ровно то, что нужно. На Хабре ibessonov предложил свое решение, а apangin — свое в комментарии. Вариант Андрея мне понравился, но вскоре выяснились некоторые связанные с ним проблемы. Во-первых, это основано на внутренних классах JDK, все это работает только в Java 8, но не в более поздних версиях. Во-вторых, этот метод имеет ряд ограничений, например для BiFunction или BiConsumer он выдает неверное значение (это как раз обсуждается в комментариях). В общем, перебрав несколько вариантов, удалось найти тот, который не имеет этих изьянов и работает в поздних версиях JDK — SerializedLambda. Забегая вперед сразу скажу, что это работает только с функциональными интерфейсами, помеченными как java.io.Serializable (т.е. с java.util.function.Function работать не будет), но в целом это не проблемное ограничение. Перед тем как перейти к решению, отвечу на резонный вопрос а зачем это может понадобиться? В моем случае это используется в тестовых фреймворках, чтобы добавить диагностическую информацию о вызываемом методе, который определялся через method reference. Это позволяет сделать одновременно лаконичный и compile-безопасный код. Например, можно сделать "where" hamcrest matcher, использующий функцию-extractor для значений: Обратите внимание, что в случае ошибки тест упадет с диагностикой "after call SamplePojo.getName". Для однострочного теста это кажется избыточным, но hamcrest-выражения могут иметь многоуровневую вложенность, поэтому лишняя детализация не помешает. Класс java.lang.invoke.SerializedLambda — это сериализованное представление лямбда-выражения. Важно уточнить, что интерфейс лямбда-выражения должен быть помечен как Serializable: Как следует из javadoc класса, чтобы получить объект SerializedLambda, следует вызвать приватный writeReplace на лямбда-объекте: Дальше все нужные детали достаем из SerializedLambda, нужно только несложное преобразование. Например, имена классов записаны через "/"(слеш) вместо точек, а примитивные типы сделаны сокращениями. Например getImplMethodSignature() возвращает строку "(Z)V", это означает один аргумент (внутри скобок) типа boolean ("Z"), тип возвращаемого значения — void ("V"): Остается только найти подходящий метод в интерфейсе, чтобы вернуть правильный результат: Работает. Тут будет другой тип serializedLambda.getImplMethodKind(). Пример: Это работает в Java 8, Java 11, Java 14, не требует внешних библиотек или доступа к приватным api JDK, не требует дополнительных параметров запуска JVM. Кроме того, применимо и к статическим методам и к методам с разным количеством аргументов (т.е. не только Function-подобные).
Единственное неудобство — для каждого вида функций придется создать сериализуемое представление, например: Полную реализацию можно найти тут. Вы можете скопировать класс в свой проект, но я бы не рекомендовал использовать это вне scope test. Кроме того, можно добавить зависимость: и вызвать