Функциональное программирование в Java получило развитие с появлением лямбда-выражений и функциональных интерфейсов (начиная с Java 8).
История вопроса
До появления Java 8 все интерфейсы были набором абстрактных методов, и парадигма была ориентирована на ООП. С введением функциональных интерфейсов и лямбда-выражений появилась возможность писать более краткий код и следовать принципам FP, что повысило читаемость и выразительность кода.
Проблема
Код, связанный с обработкой событий, коллекций или асинхронной логики, становился избыточным: приходилось создавать отдельные классы или анонимные внутренние классы. Это затрудняло поддержку и масштабирование кода.
Решение
Функциональный интерфейс — это интерфейс с ровно одним абстрактным методом. Его можно использовать как целевое назначение для лямбда-выражения. В стандартной библиотеке появились типовые функциональные интерфейсы, такие как Function<T, R>, Predicate<T>, Supplier<T>, Consumer<T>, а также возможность создавать свои интерфейсы.
Пример кода:
import java.util.function.Function; public class FunctionalExample { public static void main(String[] args) { // Стандартный функциональный интерфейс Function Function<String, Integer> stringLength = s -> s.length(); System.out.println(stringLength.apply("Java")); // Выведет 4 } }
Ключевые особенности:
Можно ли функциональный интерфейс объявить с несколькими абстрактными методами, если остальные методы имеют реализацию по умолчанию или статичны?
Нет, функциональный интерфейс может содержать только один абстрактный метод. Метод по умолчанию (default) или статический способ разрешается иметь.
Можно ли наследовать функциональный интерфейс от другого интерфейса с несколькими абстрактными методами?
Нет, если итоговый интерфейс будет иметь больше одного абстрактного метода, он перестаёт быть функциональным, и его нельзя использовать для подстановки лямбда-выражения.
Чем отличается функциональный интерфейс Java от SAM-интерфейсов в других языках, например, C#?
В Java нет прямого ключевого слова для объявлений SAM-интерфейсов до появления аннотации @FunctionalInterface. В отличие от C#, где delegate чётко задаёт сигнатуру, в Java достаточно одного абстрактного метода и опциональной аннотации для компилятора.
@FunctionalInterface — компилятор не выдаёт ошибку сразу, если интерфейс перестаёт быть функциональным.В крупном проекте решили использовать лямбды повсеместно, в том числе и там, где сущности представляли данные, с бизнес-логикой напрямую не связанные. В результате сложной логике было сложно следить, лямбды маскировали намерения кода, а отладка становилась затруднительной.
Плюсы:
Минусы:
В другом проекте тщательно анализировали, какие интерфейсы подходят для FP. Использовали Predicate, Function и свои интерфейсы для обработки коллекций и событий. Для сущностей и хранения данных FP не применяли.
Плюсы:
Минусы: