Почему в функциональном интерфейсе один метод

Ответ

Функциональный интерфейс содержит ровно один абстрактный метод (SAM - Single Abstract Method), потому что он предназначен для использования с лямбда-выражениями. Когда интерфейс имеет только один метод, компилятор может однозначно сопоставить лямбда-выражение с этим методом.

Пример:

@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
}

// Использование
Calculator add = (a, b) -> a + b;

Ключевые моменты:

  1. Аннотация @FunctionalInterface не обязательна, но помогает компилятору проверять условие SAM
  2. Может содержать default и static методы
  3. Позволяет писать более чистый и лаконичный код
  4. Основа для Java Stream API и многих других возможностей Java 8+

Ответ 18+ 🔞

А, слушай, вот это тема, про которую можно поговорить. Ну, типа, представь себе: ты пишешь код, и тебе надо передать кусок логики, как аргумент. До Java 8 это был, ёпта, просто пиздец — анонимные классы на три экрана, ебушки-воробушки, читать невозможно. А потом придумали эти интерфейсы с одним-единственным абстрактным методом. Идея-то, в общем, простая до безобразия.

Смотри, вот в чём фишка. Если в интерфейсе один абстрактный метод, то компилятор, этот хитрая жопа, может однозначно понять, на какой именно метод ты намекаешь своей лямбдой. Типа, (a, b) -> a + b. Он смотрит: "Ага, интерфейс Calculator, метод у него один — calculate. Значит, эта стрелочка — его и есть тело". И всё, магия готова. Волнение ебать, как же это удобно.

Вот смотри на пример, тут всё понятно:

@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
}

// Использование
Calculator add = (a, b) -> a + b;

Аннотацию @FunctionalInterface можно и не ставить, но я тебе скажу — ставь. Это как предупредительный знак "осторожно, злая собака". Компилятор тогда проверит, что ты не накосячил и не добавил лишний абстрактный метод. А то потом сам от себя охуеешь, когда всё сломается.

И ещё важный момент, который многие путают. Интерфейс может быть функциональным, даже если в нём есть default и static методы. Главное, чтобы абстрактный был один. Это как если у тебя в машине овердохуища кнопок (подогрев, музыка, климат), но педаль газа всё равно одна. Лямбда — это и есть нажатие на эту педаль.

Без этой штуки не было бы ни Stream API, ни половины удобств в современной Java. Так что штука архиважная. Просто запомни: один абстрактный метод — и ты король. Всё остальное — да похуй, компилятор разберётся.