Functional Interface: почему методов может быть несколько, хотя он функциональный?
Когда спрашивают:
Что такое функциональный интерфейс?
Обычно отвечают:
Интерфейс с одним абстрактным методом.
Правильно, но тогда возникает интересный вопрос:
@FunctionalInterface
public interface MyFunction {
void execute();
String toString();
int hashCode();
}
Почему это вообще компилируется? Ведь методов здесь три.
Потому что toString() и hashCode() — методы Object.
Они не считаются абстрактными методами функционального интерфейса. Поэтому это всё ещё валидный Functional Interface.
И есть ещё одна интересная деталь.
@FunctionalInterface
interface Converter {
String convert(String value);
default String convertAndTrim(String value) {
return convert(value).trim();
}
static void log(String value) {
System.out.println(value);
}
}
З
десь тоже всё нормально.
Почему?
Потому что default и static методы не являются абстрактными.
То есть правило на самом деле звучит не:
«В интерфейсе должен быть один метод»
.А:
"В интерфейсе должен быть ровно один абстрактный метод, который не является методом Object."
Именно поэтому:
Predicate<T>
Function<T, R>
Consumer<T>
Supplier<T>
Comparator<T>
можно передавать через Lambda.
Например:
Predicate<Integer> positive = x -> x > 0;
Lambda не создаёт «анонимный класс с методом».
Она реализует единственный абстрактный контракт функционального интерфейса.
А @FunctionalInterface — это не механизм, который делает интерфейс функциональным. - это проверка компилятора.
Если завтра кто-то добавит второй абстрактный метод:
@FunctionalInterface
interface Converter {
String convert(String value);
String anotherMethod(String value);
}
компилятор сразу скажет
Такой интерфейс больше не является функциональным
И вот это, пожалуй, главное:
Functional Interface определяется не количеством всех методов, а количеством абстрактных методов.