Theory
Функциональный интерфейс
Что такое функциональный интерфейс?
- Функциональный интерфейс — это интерфейс, который содержит ровно один абстрактный метод.
- Он может также содержать дефолтные и статические методы.
- Функциональные интерфейсы используются в контексте лямбда-выражений и ссылок на методы.
Пример: интерфейс
Runnable
с методомrun()
. - Для обозначения функционального интерфейса используется аннотация
@FunctionalInterface
, но её использование необязательно.
Для чего нужна аннотация @FunctionalInterface
?
Аннотация @FunctionalInterface
используется для явного обозначения интерфейса как функционального.
Она служит для следующих целей:
- Проверка компилятора: Гарантирует, что интерфейс содержит только один абстрактный метод. Если в интерфейсе более одного абстрактного метода, компилятор выдаст ошибку.
- Документация: Явно показывает, что интерфейс предназначен для использования с лямбда-выражениями или ссылками на методы, что делает код более понятным для разработчиков.
Аннотация необязательна, но её использование рекомендуется для улучшения читаемости и предотвращения ошибок.
Что такое лямбда?
- Лямбда-выражение в Java — это краткая форма записи анонимного класса, реализующего функциональный интерфейс.
- Оно позволяет писать функциональный код компактнее, убирая лишние детали, такие как объявление класса и метода.
- Лямбда-выражения используются для передачи поведения в виде аргументов, чаще всего в функциональных стилях программирования, например, при работе с коллекциями.
- Лямбда-выражения позволяют писать более выразительный и читаемый код.
Что использовали, когда лямбд не было?
До появления лямбда-выражений в Java (до версии 8), для передачи поведения или функциональности использовались анонимные внутренние классы.
Пример использования анонимного класса вместо лямбда:
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Running");
}
};
Вместо лямбда-выражений, такой код был громоздким и содержал много шаблонного кода, что делало его менее читаемым. Лямбды пришли на смену анонимным классам, чтобы сделать код более лаконичным и удобным.
Чем лямбда она отличается от анонимного класса?
Лямбда-выражения и анонимные классы в Java имеют схожие цели, но между ними есть несколько ключевых различий:
- Синтаксис:
- Лямбда: Лаконичный и компактный синтаксис, предназначенный для описания функциональности, обычно в одну строку.
- Анонимный класс: Более громоздкий синтаксис, требующий полного определения класса и его метода.
- Создание классов:
- Лямбда: Не создает нового класса на уровне байт-кода; вместо этого компилятор создает легковесный объект функционального интерфейса.
- Анонимный класс: Создает новый анонимный класс во время компиляции, что увеличивает размер байт-кода и нагрузку на память.
- Использование контекста:
- Лямбда:
Контекст
this
внутри лямбды ссылается на внешний класс, в котором лямбда определена. - Анонимный класс:
Контекст
this
ссылается на сам анонимный класс.
- Лямбда:
Контекст
- Оптимизация и производительность:
- Лямбда:
Оптимизируется компилятором и JVM с использованием
invokedynamic
, что позволяет эффективнее управлять памятью и улучшает производительность. - Анонимный класс: Менее оптимизирован, так как создает дополнительный класс, что увеличивает накладные расходы.
- Лямбда:
Оптимизируется компилятором и JVM с использованием
- Тип привязки:
- Лямбда: Привязывается к функциональному интерфейсу, ограниченному одним абстрактным методом.
- Анонимный класс: Может реализовать любой интерфейс или расширить любой класс.
- Читаемость и поддержка:
- Лямбда: Более лаконичный и читаемый код, особенно полезен в функциональном программировании.
- Анонимный класс: Код более громоздкий и трудночитаемый, особенно при сложных выражениях.
В итоге, лямбда-выражения более компактны, эффективны и удобны в использовании, чем анонимные классы, особенно когда речь идет о реализации функциональных интерфейсов.