Что такое функциональный интерфейс в 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; // Если есть подходящий статический метод

Зачем это нужно? Функциональные интерфейсы — это основа для лямбда-выражений и ссылок на методы в 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. Поставщик, волшебный мешок.

Вот и вся магия. Главное — не пытайся впихнуть в один интерфейс два абстрактных метода, а то компилятор тебе такое «в рот меня чих-пых» устроит!