Функциональный интерфейс
1. Что такое функциональный интерфейс
Чтобы иметь возможность использовать лямбда выражения, необходим интерфейс:
public interface Searchable {
boolean test(Car car);
}
Searchable s = (Car c) -> c.getCostUSD() > 20000;
Лямбда выражения не содержат информацию о том, какой функциональный интерфейс они реализуют.
Тип выражения выводится из контекста, в котором используется лямбда выражение. Этот тип называется целевой тип (target type).
Если лямбда выражение присваивается какому-то интерфейсу, лямбда выражение должно соответствовать синтаксису метода интерфейса.
Одно и то же лямбда выражение может использоваться с разными интерфейсами, если они имеют абстрактные методы, которые совместимы. Например:
interface Searchable {
boolean test(Car car);
}
interface Saleable {
boolean approve(Car car);
}
//...
Searchable s1 = c -> c.getCostUSD() > 20000;
Saleable s2 = c -> c.getCostUSD() > 20000;
Функциональный интерфейс (functional interface) – это интерфейс у которого только один абстрактный метод. Функциональный интерфейс может содержать любое количество методов по умолчанию (default) или статических методов. Например:
interface A {
default int defaultMethod() {
return 0;
}
void method();
}
Еще один пример функционального интерфейса:
interface B {
default int defaultMethod() {
return 0;
}
default int anotherDefaultMethod() {
return 0;
}
void method();
}
Функциональный интерфейс может содержать методы класса Object
:
interface A {
boolean equals(Object o);
int hashCode();
String toString();
void method();
}
В Java 8 была введена аннотация @FunctionalInterface, которая генерирует ошибку компиляции, если интерфейс не является функциональным:
// This won't compile
@FunctionalInterface
interface A {
void m(int i);
void m(long l);
}
Примеры функциональных интерфейсов: java.lang.Runnable
, java.util.Comparator.
2. Лямбда vs анонимные классы
Лямбда выражения являются альтернативой анонимным классам. Но они не одинаковы.
Общее:
- Локальные переменные могут быть использованы только если они final или effective final.
- Разрешается доступ к переменным класса и статическим переменным класса.
- Они не должны выбрасывать больше исключений чем определено в throws метода функционального интерфейса.
Различия:
- Для анонимных классов ключевое слово
this
ссылается на сам класс. Для лямбды выражений на внешний класс. - Анонимные классы компилируются во внутренние классы. Но лямбда выражения преобразуются в статические
private
методы класса, в котором они используютinvokedynamic
инструкцию. Лямбда более эффективны, так как не надо загружать еще один класс.
3. Встроенные функциональные интерфейсы
В Java 8 добавлены встроенные функциональные интерфейсы в пакет java.util.function:
Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.