Есть ли способ распечатать функциональный интерфейс?

Допустим, у меня есть интерфейс:

public interface Function {
    double function (double input);
}

Теперь предположим, что я создал экземпляр этого интерфейса где-то в моем основном классе,

Function f = (x) -> x;

Как я могу распечатать эту функцию в виде обычного текста? Итак, что-то вроде этого:

int f (double x) {return x}

Запуск .toString на этом Function печатает что-то вроде Main$1@6d06d69c. Как я могу получить представление этого интерфейса в Java?

Он не предназначен для этого. Более длинный ответ: вы можете добавить инструментарий для декомпиляции кода, но это большая работа.

Peter Lawrey 20.04.2018 20:09

Ах, воняет, в любом случае спасибо за ответ!

MazeOfEncryption 20.04.2018 20:10

Думаю, тоже. особенно для целей отладки, лямбды - это боль.

Peter Lawrey 20.04.2018 20:13

На самом деле, вы никогда не сможете распечатать фактическую реализацию какого-либо метода на Java, так почему же язык позволяет вам делать это в случае лямбда-выражений?

fps 20.04.2018 20:30

Это может быть очень полезно для целей отладки. Даже если бы это было даже не в самой java, а в функции eclipse.

MazeOfEncryption 20.04.2018 20:31

Да, абсолютно согласен с вами, это была бы классная функция

fps 20.04.2018 20:32

Это действительно может быть боль в спине. Иногда я писал своего рода методы-оболочки, такие как Function f = wrap(g, "some description");, чтобы иметь разумный toString для функции (аналогично для предикатов, как в этот класс). Но наличие что-нибудь еще по сравнению с Main$1@6d06d69c могло бы облегчить отладку много. Итак, +1, хотя я знаю, что "идеального" ответа не будет, возможно, кто-то опубликует предложения или обходные пути.

Marco13 20.04.2018 20:43

В итоге я реализовал необязательный параметр «description» в конструкторе, который использует функцию, чтобы вы могли предоставить краткое описание того, что делает метод.

MazeOfEncryption 20.04.2018 21:12
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
7
8
397
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

К сожалению, ответ (начиная с Java 9) заключается в том, что не существует простого способа заставить метод toString() дать вам значимое для человека значение для произвольного экземпляра функционального интерфейса.

Вот пара альтернатив, которые применимы для некоторых сценариев использования:

  • Вместо использования лямбда-выражения реализуйте интерфейс с помощью класса и включите соответствующее переопределение для метода toString().

  • Заполните Map<Function, String> значимыми именами для всех ваших экземпляров Function.

Теоретически было бы возможно создать библиотеку, которая может извлекать файл ".class" для (скажем) лямбды, анализировать его, определять, что делают байт-коды, а затем создавать соответствующее резюме. Но это был бы сложный проект.


Было бы неплохо, если бы для этого было простое и понятное решение. Может быть, «кто-то» мог бы предложить это как RFE для будущей версии Java.

Ответ принят как подходящий

Помните, что текст функции (иначе известный как «код») существует только тогда, когда вы его пишете. Вы компилируете это в байт-код, который затем запускается на виртуальной машине Java. Во время выполнения исходный код, который вы написали, больше не существует, и его нелегко получить.

Вам нужно явно вызвать метод в интерфейсе, указав значение double, как показано ниже.

Function f = (d) -> d;
System.out.print(f.function(2.0));

Другие вопросы по теме