Почему я не могу создать @FunctionalInterface
с реализацией метода по умолчанию?
@FunctionalInterface
public interface MyInterface {
default boolean authorize(String value) {
return true;
}
}
Почему я не могу создать @FunctionalInterface
с реализацией метода по умолчанию?
@FunctionalInterface
public interface MyInterface {
default boolean authorize(String value) {
return true;
}
}
У вас могут быть методы по умолчанию в функциональном интерфейсе , но для его контракта требуется предоставить один абстрактный метод (или 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);
}
не компилируется.
Функциональный интерфейс представляет собой 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.
Это потому, что @FunctionalInterface
может иметь методы по умолчанию, сколько угодно. Например, рассмотрим интерфейс java.util.Function
. Он содержит два метода по умолчанию: compose
и andThen
. Но должен быть точно один метод, отличный от метода по умолчанию. В противном случае, как компилятор будет знать, какой из методов по умолчанию должен быть сопоставлен лямбда?
Интерфейсы, имеющие точно один абстрактный метод, известный как функциональный интерфейс или интерфейсы с одним абстрактным методом (интерфейсы SAM).
Вы можете прочитать больше на Что такое интерфейс SAM?