Функциональные интерфейсы в Java

Функциональные интерфейсы предоставляют целевые типы для лямбда-выражений и ссылок на методы. Каждый функциональный интерфейс имеет один абстрактный метод, называемый функциональным методом для этого функционального интерфейса, к которому сопоставляются или адаптируются параметры лямбда-выражения и возвращаемые типы. Функциональные интерфейсы могут предоставлять целевой тип в нескольких контекстах, таких как контекст присвоения, контекст вызова метода или контекст приведения:

// Контекст присвоения
Predicate<String> p = String::isEmpty;

// Контекст вызова метода
stream.filter(e -> e.getSize() > 10)...

// Контекста приведения
stream.map((ToIntFunction) e -> e.getSize())...

Интерфейсы в пакете java.util.function являются функциональными интерфейсами общего назначения, используемыми JDK, а также доступны для использования в пользовательском коде. Хотя они не определяют полный набор форм функций, к которым могут быть адаптированы лямбда-выражения, они предоставляют достаточно, чтобы удовлетворить общие требования. Другие функциональные интерфейсы, предоставляемые для определенных целей, такие как FileFilter, определены в пакетах, в которых они используются.

Интерфейсы в этом пакете аннотированы FunctionalInterface. Эта аннотация не является требованием для компилятора распознавать интерфейс как функциональный, а просто помогает уловить замысел проекта и заручиться помощью компилятора в выявлении случайных нарушений замысла проекта.

Функциональные интерфейсы часто представляют абстрактные концепции, такие как функции, действия или предикаты. При документировании функциональных интерфейсов или обращении к переменным, типизированным как функциональные интерфейсы, обычно ссылаются непосредственно на эти абстрактные концепции, например, используя "эту функцию" вместо "функция, представленная этим объектом". Когда говорят, что метод API принимает или возвращает функциональный интерфейс таким образом, например "применяет предоставленную функцию к ...", это понимается как ненулевая ссылка на объект, реализующий соответствующий функциональный интерфейс, если только потенциальная недействительность явно указана.

Функциональные интерфейсы в этом пакете следуют расширяемому соглашению об именах, а именно:

  • Существует несколько основных форм функций, включая Function (унарная функция от T до R), Consumer (унарная функция от T до void), Predicate (унарная функция от T до логического значения) и Supplier (функция с нулевым значением для R).
  • Функциональные формы имеют естественную арность в зависимости от того, как они чаще всего используются. Базовые формы могут быть изменены с помощью префикса арности, чтобы указать другую арность, например BiFunction (двоичная функция от T и U до R).
  • Существуют дополнительные производные функциональные формы, которые расширяют базовые функциональные формы, в том числе UnaryOperator (расширяет функцию) и BinaryOperator (расширяет BiFunction).
  • Параметры типов функциональных интерфейсов могут быть преобразованы в примитивы с дополнительными префиксами типов. Чтобы специализировать возвращаемый тип для типа, который имеет как универсальный тип возвращаемого значения, так и универсальные аргументы, мы добавляем префикс ToXxx, как в ToIntFunction. В противном случае аргументы типа специализированы слева направо, как в DoubleConsumer или ObjIntConsumer. (Префикс типа Obj используется, чтобы указать, что мы не хотим специализировать этот параметр, но хотим перейти к следующему параметру, как в ObjIntConsumer.) Эти схемы можно комбинировать, как в IntToDoubleFunction.
  • Если для всех аргументов есть префиксы специализации, префикс арности можно не указывать (как в ObjIntConsumer).

Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки