Подтвердить что ты не робот

Может ли @FunctionalInterfaces использовать методы по умолчанию?

Почему я не могу создать @FunctionalInterface с реализацией метода по умолчанию?

@FunctionalInterface
public interface MyInterface {
    default boolean authorize(String value) {
        return true;
    }
}
4b9b3361

Ответ 1

У вас могут быть методы по умолчанию в функциональном интерфейсе , но для его контракта требуется предоставить один абстрактный метод (или SAM). Поскольку метод по умолчанию имеет реализацию, он не абстрактный.

Концептуально функциональный интерфейс имеет ровно один абстрактный метод. Поскольку методы по умолчанию имеют реализацию, они не абстрактны.

и

Если тип аннотируется с этим типом аннотации, компиляторы требуется для генерации сообщения об ошибке, если:

Тип - это тип интерфейса, а не тип аннотации, перечисление или класс.

Аннотированный тип удовлетворяет требованиям функционального интерфейс.

Здесь вы не удовлетворяете требованиям функционального интерфейса, поэтому вам нужно предоставить один абстрактный метод. Например:

@FunctionalInterface
interface MyInterface {

    boolean authorize(int val);

    default boolean authorize(String value) {
        return true;
    }
}

Обратите внимание: если вы объявляете абстрактный метод, переопределяющий один из общедоступного метода из класса Object, он не учитывается, поскольку любая реализация этого интерфейса будет иметь реализацию этих методов, по крайней мере, по классу Object. Например:

@FunctionalInterface
interface MyInterface {

    default boolean authorize(String value) {
        return true;
    }

    boolean equals(Object o);
}

не компилируется.

Ответ 2

Функциональный интерфейс представляет собой interface, имеющий единственный абстрактный метод. Вся цель определения функциональных интерфейсов заключается в том, чтобы обеспечить реализацию единого абстрактного метода с помощью лямбда-выражений, который будет эффективно переопределять этот метод, который делает реализацию default для него бессмысленной.

Наличие interface, состоящего полностью из методов default, вызывает множество проблем. Существует техническая проблема, которую не может решить компилятор для выражения лямбда, метод которого реализуется, когда существует несколько методов default, и существует семантическая проблема, заключающаяся в том, что interface, состоящий полностью из методов default, не является abstract. Вы не можете создать экземпляр этого поведения по умолчанию, поскольку вы не можете создать экземпляр interface и заставляете программистов создавать конкретные классы только для вызова поведения по умолчанию, которое, поскольку интерфейсы не имеют состояния, может быть предоставлено одним символом:

@FunctionalInterface
public interface MyInterface {
    static MyInterface DEFAULT = s->true;
    boolean authorize(String value);
}

Обратите внимание, что вы можете иметь интерфейсы, расширяющие функциональный интерфейс и предоставляющие по умолчанию метод, если вам нужно. Тем не менее, если это приведет к созданию interface без абстрактных методов, я бы поставил под вопрос дизайн. Вы можете сравнить с обсуждение интерфейсов маркеров с методами default. Если суб-интерфейс будет иметь разные абстрактные методы, чем функциональный интерфейс, это будет другая история. Для этого могут быть реальные варианты использования, но эти суб-интерфейсы также продемонстрируют, почему они не должны смешиваться с функциональной базой interface, поскольку выражение lambda всегда будет применять метод abstract.

Ответ 3

Это потому, что @FunctionalInterface может иметь методы по умолчанию, сколько угодно. Например, рассмотрим интерфейс java.util.Function. Он содержит два метода по умолчанию: compose и andThen. Но должен быть точно один метод, отличный от метода по умолчанию. В противном случае, как компилятор будет знать, какой из методов по умолчанию должен быть сопоставлен лямбда?

Ответ 4

Интерфейсы, имеющие точно один абстрактный метод, известный как функциональный интерфейс или интерфейсы с одним абстрактным методом (интерфейсы SAM).

  • Требуется только один абстрактный метод
  • @FunctionalInterface аннотация может быть добавлена
  • Методы по умолчанию не являются абстрактными, поэтому мы можем добавить любое количество методов по умолчанию
  • Позволяет переопределять методы класса Object как абстрактные
  • Функциональные (SAM) интерфейсы очень важны для написания лямбда-выражения
  • Многие функциональные (SAM) интерфейсы добавляются в java 8 в пакете java.util.function.

Вы можете прочитать больше на Что такое интерфейс SAM?