← Назад к вопросам

Сколько методов может быть в функциональном интерфейсе?

1.0 Junior🔥 113 комментариев
#Kotlin основы

Комментарии (3)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Функциональные интерфейсы в Java

Ключевой принцип функционального интерфейса в Java (с версии 8+) заключается в том, что он должен содержать ровно один абстрактный метод. Это единственное требование, определённое спецификацией языка для того, чтобы интерфейс можно было использовать в качестве целевого типа для лямбда-выражения или ссылки на метод.

Сколько методов должно быть?

  • Обязательно один абстрактный метод. Это его "функциональный дескриптор".
  • При этом может быть любое количество default-методов и static-методов. Они имеют реализацию внутри самого интерфейса и не нарушают правило "одного абстрактного метода".
  • Могут быть методы, унаследованные от java.lang.Object. Компилятор Java не считает их абстрактными для целей функционального интерфейса, так как их реализация уже существует в Object.

Пример и пояснение

Рассмотрим стандартный функциональный интерфейс Predicate<T>:

@FunctionalInterface
public interface Predicate<T> {
    // Единственный абстрактный метод (SAM - Single Abstract Method)
    boolean test(T t);

    // default-методы (их может быть много)
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    // static-метод (их тоже может быть много)
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

В этом интерфейсе:

  1. test(T t)единственный абстрактный метод.
  2. and, negate, or — три default-метода с готовой реализацией.
  3. isEqualstatic-метод.

Аннотация @FunctionalInterface

Эта аннотация не делает интерфейс функциональным, а выполняет роль строгой проверки на этапе компиляции. Если мы пометим интерфейс этой аннотацией, но объявим в нём более одного абстрактного метода, компилятор выдаст ошибку.

@FunctionalInterface
interface MyFunctionalInterface {
    void execute(); // OK

    // void anotherAbstractMethod(); // ОШИБКА КОМПИЛЯЦИИ!
    // Аннотация @FunctionalInterface не позволит это скомпилировать.
}

Важные исключения и нюансы

  1. Методы java.lang.Object: Абстрактные методы, которые являются переобъявлениями публичных методов java.lang.Object (например, equals, hashCode, toString), не учитываются при подсчёте. Поэтому следующий интерфейс по-прежнему является функциональным:

    @FunctionalInterface
    interface ComplexFunctionalInterface {
        void doWork();
        boolean equals(Object obj); // Не считается за "лишний" абстрактный метод
        String toString(); // Не считается
    }
    
  2. Интерфейс без методов? Нет, интерфейс без абстрактных методов (даже если в нём есть default или static методы) НЕ является функциональным. Ему нечего будет реализовывать с помощью лямбды.

  3. Интерфейс с двумя абстрактными методами (без учёта методов Object) не является функциональным и не может быть использован с лямбда-выражениями.

Вывод

Таким образом, в функциональном интерфейсе может и должен быть ровно один абстрактный метод (SAM). При этом общее количество методов в нём может быть практически любым, так как к одному абстрактному методу можно добавлять неограниченное количество default- и static-методов, а также неограниченно переобъявлять методы из Object. Это ограничение "одного абстрактного метода" — фундаментальная концепция, лежащая в основе всей системы функционального программирования, добавленной в Java 8, и позволяющая использовать краткий синтаксис лямбда-выражений ((args) -> body).

Сколько методов может быть в функциональном интерфейсе? | PrepBro