Короткий ответ
Лямбда-выражение — это анонимная функция: блок кода без имени, который можно передавать как значение, например в аргументы метода. В Java 8 оно записывается как список параметров, стрелка и тело. Лямбда реализует единственный абстрактный метод функционального интерфейса, а типы параметров и возвращаемого значения компилятор выводит автоматически (type inference) из контекста.
Как это работает подробнее
Функциональный интерфейс (SAM-интерфейс) — это интерфейс ровно с одним абстрактным методом; в нём могут быть также статические и default-методы. Аннотация @FunctionalInterface необязательна, но позволяет компилятору проверить, что интерфейс действительно функциональный.
До Java 8 такое поведение реализовывали анонимными внутренними классами; лямбда — более компактная альтернатива им. Встроенные примеры — Runnable, Comparator, Callable, а в Java 8 добавлены Function, Consumer, Supplier, Predicate и другие интерфейсы пакета java.util.function.
- Лямбда не создаёт новый уровень вложенности, как анонимный класс: this внутри неё ссылается на окружающий объект.
- Захватываемые лямбдой локальные переменные должны быть effectively final.
- Лямбды активно применяются в Stream API и методах коллекций вроде forEach и removeIf.
Пример кода
public class LambdaExample {
@FunctionalInterface
interface Calculator {
int calc(int a, int b);
}
public static void main(String[] args) {
// анонимный класс (Java 5+)
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Привет");
}
};
// то же самое лямбдой (Java 8+)
Runnable r2 = () -> System.out.println("Привет");
// функциональный интерфейс + лямбда
Calculator add = (a, b) -> a + b;
System.out.println(add.calc(2, 3)); // 5
}
}Что использовать на практике
- Используйте стандартные функциональные интерфейсы из java.util.function: Predicate, Function, Consumer, Supplier.
- Применяйте лямбды вместо анонимных классов для краткости и читаемости, особенно в Stream API.
- Помечайте свои SAM-интерфейсы аннотацией @FunctionalInterface, чтобы компилятор проверил структуру.
Подводные камни
- Интерфейс с двумя абстрактными методами не является функциональным — лямбда к нему неприменима.
- Лямбда не имеет собственного this и может захватывать только effectively final переменные.
- Не прячьте в «однострочную» лямбду сложную логику: выносите её в отдельный метод и используйте ссылку на метод.
Как отвечать на собеседовании
- Определите лямбду как анонимную функцию → свяжите её с функциональным интерфейсом (SAM) → покажите синтаксис и пример → сравните с анонимным классом → перечислите стандартные интерфейсы java.util.function.