Функциональный интерфейс в Java - Вопросы
Всего: 5 вопросов
1. Что такое функциональный интерфейс в Java?
Что такое функциональный интерфейс в Java?
Функциональный интерфейс — это интерфейс ровно с одним абстрактным методом (SAM, Single Abstract Method). Такой интерфейс может быть целевым типом лямбда-выражения или ссылки на метод. Количество default-, static-, private- и private static-методов не ограничено (последние два — с Java 9), а абстрактные объявления, повторяющие public-методы класса Object (equals, hashCode, toString), при подсчёте не учитываются. Примеры из JDK: Runnable, Callable, Comparator, Iterable.
2. Что такое функциональный дескриптор (function descriptor)?
Что такое функциональный дескриптор (function descriptor)?
Функциональный дескриптор — это сигнатура абстрактного метода функционального интерфейса, то есть форма лямбда-выражения, которое может его реализовать. Записывается как параметры -> тип возвращаемого значения; имя метода в дескриптор не входит. Примеры: у void doSomething() дескриптор () -> void, у int someMethod1(String param) — String -> int, у void someMethod2(int a1, int a2) — (int, int) -> void, у Consumer<T> — T -> void.
3. Почему Comparator остаётся функциональным интерфейсом, хотя объявляет два абстрактных метода — compare(T, T) и equals(Object)?
Почему Comparator остаётся функциональным интерфейсом, хотя объявляет два абстрактных метода — compare(T, T) и equals(Object)?
Потому что абстрактные объявления, повторяющие public-методы класса Object, при подсчёте не учитываются. Любой класс, реализующий интерфейс, уже наследует equals, hashCode и toString от Object, поэтому лямбде нечего в них реализовывать — компилятор исключает такие объявления. Фактически абстрактный метод у Comparator один, compare, поэтому аннотация @FunctionalInterface на нём стоит совершенно законно и строка Comparator<Car> byCost = (a, b) -> a.getCostUSD() - b.getCostUSD(); компилируется.
4. Что такое целевой тип (target type) лямбда-выражения и откуда он берётся?
Что такое целевой тип (target type) лямбда-выражения и откуда он берётся?
Само лямбда-выражение не содержит информации о том, какой интерфейс оно реализует. Тип выводится компилятором из контекста использования и называется целевым типом. Он берётся из объявления переменной (Searchable s = c -> ...;), параметра метода (list.removeIf(c -> ...)), возвращаемого значения метода, приведения типа, тернарного оператора или инициализатора массива. Отсюда следствие: одна и та же лямбда подходит разным интерфейсам, если совпадают список параметров, возвращаемый тип и объявленные исключения (имена абстрактных методов роли не играют). Код без целевого типа не компилируется: var f = () -> System.out.println("hi"); и Object o = c -> c.getCostUSD() > 20000; дают ошибку компиляции.
5. Какие готовые функциональные интерфейсы есть в пакете java.util.function?
Какие готовые функциональные интерфейсы есть в пакете java.util.function?
Основные: Predicate<T> с методом boolean test(T t) — проверка условия; Consumer<T> с void accept(T t) — действие без результата; Function<T, R> с R apply(T t) — преобразование значения; Supplier<T> с T get() — поставка значения без аргументов; UnaryOperator<T> и BinaryOperator<T> — частные случаи Function, у которых аргументы и результат одного типа; двухаргументные BiFunction<T, U, R>, BiPredicate<T, U>, BiConsumer<T, U>. Для примитивов есть специализации без автоупаковки: IntPredicate, IntFunction<R>, ToIntFunction<T>, IntUnaryOperator, IntBinaryOperator, IntSupplier, IntConsumer и их аналоги для long и double. Вне пакета функциональными являются также Runnable, Callable<V>, Comparator<T>, Iterable<T> и AutoCloseable.