Lambda · Урок 2/10
20%
⏱ 5 минут чтения

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

  1. Что такое функциональный интерфейс
  2. Лямбда vs анонимные классы
  3. Встроенные функциональные интерфейсы

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 анонимные классы

Лямбда выражения являются альтернативой анонимным классам. Но они не одинаковы.

Общее:

  1. Локальные переменные могут быть использованы только если они final или effective final.
  2. Разрешается доступ к переменным класса и статическим переменным класса.
  3. Они не должны выбрасывать больше исключений чем определено в throws метода функционального интерфейса.

Различия:

  1. Для анонимных классов ключевое слово this ссылается на сам класс. Для лямбды выражений на внешний класс.
  2. Анонимные классы компилируются во внутренние классы. Но лямбда выражения преобразуются в статические private методы класса, в котором они используют invokedynamic инструкцию. Лямбда более эффективны, так как не надо загружать еще один класс.

3. Встроенные функциональные интерфейсы

В Java 8 добавлены встроенные функциональные интерфейсы в пакет java.util.function:

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

‹ Предыдущий урок Следующий урок ›