JavaRush /Java блог /Архив info.javarush /Введение в функциональные интерфейсы
minuteman
32 уровень

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

Статья из группы Архив info.javarush
прошу сильно не тролить, только начинаю переводить статьи Введение в функциональные интерфейсы - 1

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

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

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 которая используется для выдачи ошибок на уровне компилятора, когда интерфейс который Вы аннотировали не работает на функциональном уровне. Давайте посмотрим на простой функциональный интерфейс с одним абстрактным методом:

@FunctionalInterface
public interface SimpleFunInterface {
    public void doWork();
}
Интерфейс также может объявлять абстрактные методы из класса java.lang.Object, но и в этом случае интерфейс может объявляться функциональным:

@FunctionalInterface
public interface SimpleFuncInterface {
    public void doWork();
    public String toString();
    public Boolean equals(Object o);
}
Как только Вы добавили еще один абстрактный метод в интерфейс IDE пометит его ошибочным как на картинке: Введение в функциональные интерфейсы - 2
Что еще почитать:

Группа Random:

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

@FunctionalInterface
public interface ComplexFunctionalInterface extends SimpleFuncInterface {
    default public void doSomeWork() {
        System.out.println("Doing some work in interface impl...");
    }
    default public void doSomeWork() {
        System.out.println("Doing some other work in interface impl...");
    }
}
Верхний пример до сих пор является функциональным интерфейсом. Теперь давайте рассмотрим, как мы можем использовать лямбда-выражения для замены анонимного внутреннего класса для реализации функциональных интерфейсов:

/*
*Implementation the interface by creating an
*anonymoous inner class versus using
*lambda expression.
*/
public class SimpleFunInterfaceTest {
    public static void main(String[] args) {
        carryOutWork(new SimpleFunInterface() {
            @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.work();
    }
}
Результат программы будет следующим:

Do work in SimpleFun impl...
Do work in lambda exp impl...
В случае если вы используете IDE, которая поддерживает синтаксис Java лямбда-выражений (Netbeans 8 Nightly builds) – Вы получаете подсказку, когда используете анонимные внутренние классы: Введение в функциональные интерфейсы - 3 Это был краткий ввод в концепцию функциональных интерфейсов в Java 8, а также как они могут быть реализованы с помощью лямбда-выражений.
Комментарии (7)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Ilya Sukhov Уровень 40
13 июня 2019
пример с анонимным классом у меня заработал только после замены SimpleFunInterface на SimpleFuncInterface в строке 8 и замены sfi.work на sfi.doWork в строке 17 Это нормально или я что-то не понимаю?
Di Уровень 38
5 мая 2019
Спасибо! очень простой и доступный материал! 15 минут чтения и в головке на свои места стали сразу несколько пунктов:)
mark Уровень 30
21 декабря 2014
Я немного не понял с этим примером
@FunctionalInterface
public interface ComplexFunctionalInterface extends SimpleFuncInterface {
    default public void doSomeWork() {
        System.out.println("Doing some work in interface impl...");
    }
    default public void doSomeWork() {
        System.out.println("Doing some other work in interface impl...");
    }
}

Интерфейс может содержать только один абстрактный метод и множество дефолтных методов.
1. Почему у этих методов есть реализация, если они в интерфейсе?
2. Если мы в каком-то классе наследуем интерфейс ComplexFunctional Interface, как мы поймен какой doSomeWork мы вызовем?
3. никогда до этого не встречался с default public void… это нововедение Java 8, или мне нужно что-то почитать?
Спасибо