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



Java 8 добавила много возможностей писать короткий и выразительный код. Одна из них — функциональный интерфейс (ФИ).



Интерфейс считается функциональным, если у него только один абстрактный метод. Это единственное требование, даже аннотация FunctionalInterface необязательна. Например, у интерфейса Comparable всего один метод, по определению он функциональный, но аннотации у него нет. Во всём остальном ФИ - это обычный интерфейс. У метода можно объявлять исключения и использовать любые типы параметров:

@FunctionalInterface

public interface Archiver{

void archive(String file)

throws FileNotFoundEx;

}



Экземплярами ФИ могут быть:

🔸Лямбда-выражение

🔸Ссылка на метод

🔸Ссылка на конструктор



Для большинства задач подойдут стандартные интерфейсы из пакета java.util.function. Всего их 43, но можно выделить 5 групп:

1️⃣ Consumer (потребитель)

Метод принимает один параметр и ничего не возвращает.

Consumer<String> c = 

System.out::println;



2️⃣ Supplier (поставщик)

Ничего не принимает, но возвращает значение.

Supplier<List> s = 

ArrayList::new;



3️⃣ Function

Принимает один параметр, возвращает одно значение:

Function<String,Long> map = 

s -> Long.valueOf(s);



4️⃣ UnaryOperator

Метод принимает один параметр и возвращает значение того же типа:

UnaryOperator<Integer> inc = 

i -> i+1;



5️⃣ Predicate

Принимает аргумент и возвращает boolean значение.

Predicate<String> filter = 

s -> !s.isEmpty()

&& !s.contains("q");



У этих ФИ есть удобные вариации:

🔹BiConsumer, BiFunction, BiPredicate, BinaryOperator принимают два аргумента:

BiConsumer<Integer,Integer> b = 

(x,y) -> println(x+y);



🔹LongFunction, LongSupplier , ToLongFunction и т.д позволяют не прописывать типы аргументов или выходных значений:

LongFunction<String> to = 

Long::toString;



Ответ на вопрос перед постом:

Интерфейс становится функциональным если в нём есть один абстрактный метод. Все остальные свойства у него такие же, как у обычного интерфейса. Аннотация FunctionalInterface не обязательна, но желательна для понимания кода.