Статьи

Введение в функциональные интерфейсы — концепция, воссозданная в Java 8

Любой разработчик Java во всем мире использовал бы по крайней мере один из следующих интерфейсов: java.lang.Runnable, java.awt.event.ActionListener, java.util.Comparator, java.util.concurrent.Callable. Среди заявленных интерфейсов есть некоторая общая особенность, и у них есть только один метод, объявленный в их определении интерфейса. В JDK таких интерфейсов гораздо больше, а также больше, созданных разработчиками Java. Эти интерфейсы также называются интерфейсами S- единого абстрактного метода (интерфейсы SAM). И популярным способом их использования является создание классов Anonymous Inner с использованием этих интерфейсов, что-то вроде:

01
02
03
04
05
06
07
08
09
10
public class AnonymousInnerClassTest {
  public static void main(String[] args) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println('A thread created and running ...');
      }
    }).start();
  }
}

В Java 8 та же концепция интерфейсов SAM воссоздается и называется функциональными интерфейсами. Они могут быть представлены с использованием лямбда-выражений , ссылок на методы и ссылок на конструкторы (я расскажу об этих двух темах в следующих публикациях в блоге) Введена аннотация @FunctionalInterface, которую можно использовать для ошибок уровня компилятора, когда аннотированный интерфейс не является допустимым функциональным интерфейсом. Давайте попробуем взглянуть на простой функциональный интерфейс только с одним абстрактным методом:

1
2
3
4
@FunctionalInterface
public interface SimpleFuncInterface {
  public void doWork();
}

Интерфейс также может объявлять абстрактные методы из класса java.lang.Object, но все же интерфейс может быть вызван как функциональный интерфейс:

1
2
3
4
5
6
@FunctionalInterface
public interface SimpleFuncInterface {
  public void doWork();
  public String toString();
  public boolean equals(Object o);
}

Как только вы добавите другой абстрактный метод в интерфейс, компилятор / IDE отметит его как ошибку, как показано на скриншоте ниже:

Ошибка функционального интерфейса

Интерфейс может расширять другой интерфейс, и в случае, если Интерфейс расширяется функционально и не объявляет никаких новых абстрактных методов, тогда новый интерфейс также функционален. Но интерфейс может иметь один абстрактный метод и любое количество стандартных методов, и интерфейс все равно будет называться функциональным интерфейсом. Чтобы получить представление о методах по умолчанию, пожалуйста, прочитайте здесь .

1
2
3
4
5
6
7
8
9
@FunctionalInterface
public interface ComplexFunctionalInterface extends SimpleFuncInterface {
  default public void doSomeWork(){
    System.out.println('Doing some work in interface impl...');
  }
  default public void doSomeOtherWork(){
    System.out.println('Doing some other work in interface impl...');
  }
}

Вышеуказанный интерфейс все еще является действующим функциональным интерфейсом. Теперь давайте посмотрим, как мы можем использовать лямбда-выражение по сравнению с анонимным внутренним классом для реализации функциональных интерфейсов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
/*
* Implementing the interface by creating an
* anonymous inner class versus using
* lambda expression.
*/
public class SimpleFunInterfaceTest {
  public static void main(String[] args) {
    carryOutWork(new SimpleFuncInterface() {
      @Override
      public void doWork() {
        System.out.println('Do work in SimpleFun impl...');
      }
    });
    carryOutWork(() -> System.out.println('Do work in lambda exp impl...'));
  }
  public static void carryOutWork(SimpleFuncInterface sfi){
    sfi.doWork();
  }
}

И результат будет …

1
2
Do work in SimpleFun impl...
Do work in lambda exp impl...

Если вы используете IDE, которая поддерживает синтаксис Java-лямбда-выражений ( сборки Netbeans 8 Nightly ), то при использовании анонимного внутреннего класса это дает подсказку, как описано выше:

Функциональный интерфейс Подсказка
Это было краткое введение в концепцию функциональных интерфейсов в Java 8, а также о том, как их можно реализовать с помощью лямбда-выражений.

Ссылка: Введение в функциональные интерфейсы — концепция, воссозданная в Java 8 от нашего партнера по JCG Мохамеда Санаулла в блоге Experiences Unlimited .