Ответ
Функциональный интерфейс — это интерфейс, который содержит ровно один абстрактный метод (SAM — Single Abstract Method). Он может содержать любое количество default или static методов. Аннотация @FunctionalInterface является необязательной, но явно указывает на назначение интерфейса и позволяет компилятору проверить это условие.
Пример объявления и использования:
@FunctionalInterface
interface MathOperation {
int execute(int a, int b); // Единственный абстрактный метод
default void printResult(int result) { // default-метод допустим
System.out.println("Result: " + result);
}
}
// Реализация с помощью лямбда-выражения:
MathOperation addition = (x, y) -> x + y;
int sum = addition.execute(5, 3); // 8
// Реализация с помощью ссылки на метод:
MathOperation multiply = Math::multiplyExact; // Если есть подходящий статический метод
Зачем это нужно? Функциональные интерфейсы — это основа для лямбда-выражений и ссылок на методы в Java. Они широко используются в Stream API и других API, требующих передачи поведения.
Стандартные функциональные интерфейсы из java.util.function:
Function<T, R>— принимает T, возвращает R.Predicate<T>— принимает T, возвращаетboolean.Consumer<T>— принимает T, не возвращает ничего (void).Supplier<T>— не принимает аргументов, возвращает T.
Ответ 18+ 🔞
А, слушай, вот эта штука с функциональными интерфейсами — это ж, блядь, основа всего этого цирка с лямбдами в Java! Представь себе, что это такой интерфейс, который, по сути, кричит: «У меня тут только одна работа, один абстрактный метод, и всё, больше от меня нихуя не ждите!»
Ну, формально, он может содержать ровно один абстрактный метод (этот SAM — Single Abstract Method, ёпта). А вот default или static методов — хоть овердохуища, это не запрещено. Аннотация @FunctionalInterface — она как красная табличка «осторожно, злая собака». Необязательная, но если повесил, а собака окажется с двумя головами (то есть методами), компилятор тебе сразу: «Мудак, блядь, переделывай!».
Вот, смотри, как это объявляется и используется, на примере:
@FunctionalInterface
interface MathOperation {
int execute(int a, int b); // Вот он, единственный абстрактный метод, звезда вечера!
default void printResult(int result) { // default-метод — это как бесплатный гарнир, можно
System.out.println("Result: " + result);
}
}
// А реализовать эту хрень теперь — раз плюнуть, лямбдой:
MathOperation addition = (x, y) -> x + y;
int sum = addition.execute(5, 3); // Получится 8, если ты, конечно, не проебал арифметику
// Или вот, ссылкой на метод, если лень пальцы шевелить:
MathOperation multiply = Math::multiplyExact; // При условии, что такой статический метод есть
А зачем весь этот сыр-бор? Да затем, что эти интерфейсы — это как раз та дверь, в которую врываются лямбда-выражения и ссылки на методы. Без них Stream API был бы просто грустной коллекцией, а не тем, во что можно запихивать поведение на лету, блядь.
И не выдумывай велосипед, там уже всё придумано в java.util.function! Запомни основных персонажей:
Function<T, R>— взял T, выплюнул R. Преобразователь, блядь.Predicate<T>— взял T, сказалboolean(true/false). Судья, ебать.Consumer<T>— взял T, съел, ничего не вернул (void). Потребитель, что с него взять.Supplier<T>— нихуя не взял, но выдал T. Поставщик, волшебный мешок.
Вот и вся магия. Главное — не пытайся впихнуть в один интерфейс два абстрактных метода, а то компилятор тебе такое «в рот меня чих-пых» устроит!