Я встретил новый термин в Java 8: «функциональный интерфейс». Я мог найти только одно применение при работе с лямбда-выражениями .
Java 8 предоставляет несколько встроенных функциональных интерфейсов, и если мы хотим определить какой-либо функциональный интерфейс, мы можем использовать @FunctionalInterface
аннотацию. Это позволит нам объявить только один метод в интерфейсе.
Например:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
Насколько это полезно в Java 8, кроме работы с лямбда-выражениями ?
(Вопрос здесь отличается от того, который я задавал. Он спрашивает, зачем нам нужны функциональные интерфейсы при работе с лямбда-выражениями. Мой вопрос: почему другие применения используются функциональными интерфейсами помимо с лямбда-выражениями?)
Ответы:
@FunctionalInterface
аннотация полезна для проверки времени компиляции вашего кода. Вы не можете иметь более одного метода , кромеstatic
,default
и абстрактные методы , которые переопределяют методы вObject
в вашей@FunctionalInterface
или любой другой интерфейс , используемый в качестве функционального интерфейса.Но вы можете использовать лямбда-выражения без этой аннотации, а также переопределять методы без
@Override
аннотации.Из документов
Это можно использовать в лямбда-выражении:
Это нельзя использовать в лямбда-выражении:
Но это даст ошибку компиляции :
источник
java.lang.Object
функциональном интерфейсе.public
метода, кроме какstatic
иdefault
" ...Документация делает на самом деле разница между целью
и вариант использования
чья формулировка не исключает других случаев использования в целом. Поскольку основной целью является указание на функциональный интерфейс , ваш фактический вопрос сводится к «Есть ли другие варианты использования для функциональных интерфейсов, кроме лямбда-выражений и ссылок на метод / конструктор?»
поскольку функциональным интерфейсом является языковой конструкцией Java, определенной в Спецификации языка Java, только эта спецификация может ответить на этот вопрос:
JLS §9.8. Функциональные интерфейсы :
Таким образом, спецификация языка Java не говорит иначе, единственный случай использования, упомянутый в этом разделе, - это создание экземпляров интерфейса с помощью выражений ссылок на методы и лямбда-выражений. (Это включает ссылки на конструктор, поскольку они отмечены как одна из форм выражения ссылки на метод в спецификации).
Так что в одном предложении нет, в Java 8 нет другого варианта использования.
источник
public static String generateTaskId()
а не для того, чтобы сделать ее более «функциональной», кто-то другой решил написать ее так же, какpublic class TaskIdSupplier implements Supplier<String>
при использованииget
метода, использующего реализация существующего поколения. Это неправильное использование функциональных интерфейсов, особенно повторное использованиеSupplier
встроенного JDK? PS: я не мог найти лучшее место / Q & A, чтобы спросить это. Рад мигрировать, если вы могли бы предложить.TaskIdSupplier
. Теперь вопрос в том, почему вы создали названный класс. Существуют сценарии, где требуется такой именованный тип, например, когда вы хотите поддержать поиск реализации черезServiceLoader
. Нет ничего плохого в том, чтобы позволить ему реализовать этоSupplier
. Но когда вам это не нужно, не создавайте его. Когда вам нужно только aSupplier<String>
, уже достаточно использоватьDeclaringClass::generateTaskId
и исключить необходимость явного класса - вот смысл этой языковой функции.TaskIdSupplier
реализация стоила затраченных усилий, но тогда концепцияServiceLoader
полностью скинула мне с ума. Встречаются несколько вопросов в ходе этих дискуссий , которые мы имели , такие как Что такое использованиеSupplier
«Spublic
существования , когда можно идти вперед и развивать свои собственные интерфейсы? и почему бы не иметьpublic static Supplier<String> TASK_ID_SUPPLIER = () ->...
в качестве глобальной константы? , (1/2)variable.genericMethodName(args)
вместоmeaningfulMethodName(args)
. Использование типа класса для представления функции, будь то с помощью лямбда-выражения / ссылки на метод или вручную созданного класса, является лишь средством передачи функции (при отсутствии истинных типов функций в Java). Это должно быть сделано только при необходимости.Как уже говорили другие, функциональный интерфейс - это интерфейс, который предоставляет один метод. Может иметь более одного метода, но все остальные должны иметь реализацию по умолчанию. Причина, по которой он называется «функциональным интерфейсом», заключается в том, что он эффективно действует как функция. Поскольку вы можете передавать интерфейсы как параметры, это означает, что функции теперь являются «первоклассными гражданами», как в функциональных языках программирования. Это имеет много преимуществ, и вы увидите их довольно часто при использовании Stream API. Конечно, лямбда-выражения являются основным очевидным использованием для них.
источник
Не за что. Лямбда-выражения - это единственная точка этой аннотации.
источник
@Override
если бы вы сообщили компилятору, что вы намеревались написать что-то «функциональное» (и получите ошибку, если вы поскользнулись)Лямбда-выражение может быть назначено функциональному типу интерфейса, но также могут быть ссылки на методы и анонимные классы.
Хорошая особенность конкретных функциональных интерфейсов в
java.util.function
том, что они могут быть созданы для создания новых функций (например,Function.andThen
иFunction.compose
,Predicate.and
и т. Д.) Благодаря удобным методам по умолчанию, которые они содержат.источник
Интерфейс только с одним абстрактным методом называется функциональным интерфейсом. Использование @FunctionalInterface не обязательно, но рекомендуется использовать его с функциональными интерфейсами, чтобы избежать случайного добавления дополнительных методов. Если интерфейс аннотирован аннотацией @FunctionalInterface, и мы пытаемся использовать более одного абстрактного метода, он выдает ошибку компилятора.
источник
Функциональный интерфейс:
Пример 1:
Пример 2:
Пример 3:
Java8 аннотация -
@FunctionalInterface
Приложения функционального интерфейса:
Чтобы изучить функциональные интерфейсы, изучить первые стандартные методы в интерфейсе, а после изучения функционального интерфейса вам будет легко понять ссылку на метод и лямбда-выражение
источник
Вы можете использовать лямбду в Java 8
Для получения дополнительной информации о Java Lambdas и FunctionalInterfaces
источник
@FunctionalInterface
Это новая аннотация, выпущенная с Java 8 и предоставляющая целевые типы для лямбда-выражений, и она используется при проверке времени компиляции вашего кода.Когда вы хотите использовать это:
1- Ваш интерфейс не должен иметь более одного абстрактного метода, в противном случае будет выдана ошибка компиляции.
1- Ваш интерфейс должен быть чистым, что означает, что функциональный интерфейс предназначен для реализации классами без сохранения состояния, примером чистого является
Comparator
интерфейс, потому что он не зависит от состояния разработчиков, в данном случае Нет ошибку компиляции будет дана, но во многих случаях не сможет использовать лямбда с такими интерфейсамиjava.util.function
Пакет содержит различные функциональные интерфейсы общего назначения , такие какPredicate
,Consumer
,Function
, иSupplier
.Также обратите внимание, что вы можете использовать лямбды без этой аннотации.
источник
Помимо других ответов, я думаю, что основная причина «почему использование функционального интерфейса, отличного от непосредственно лямбда-выражений» может быть связана с природой языка Java, который является объектно-ориентированным.
Основные атрибуты лямбда-выражений: 1. Они могут передаваться через 2. и могут выполняться в будущем через определенное время (несколько раз). Теперь, чтобы поддержать эту функцию в языках, некоторые другие языки решают эту проблему просто.
Например, в Java Script, функция (анонимная функция или литералы функций) может быть адресована как объект. Таким образом, вы можете создавать их просто, а также они могут быть назначены на переменную и так далее. Например:
или через ES6, вы можете использовать функцию стрелки.
До настоящего времени разработчики языка Java не соглашались обрабатывать упомянутые функции таким образом (методы функционального программирования). Они считают, что язык Java является объектно-ориентированным, и поэтому они должны решить эту проблему с помощью объектно-ориентированных методов. Они не хотят упускать простоту и последовательность языка Java.
Поэтому они используют интерфейсы, так как, когда нужен объект интерфейса только с одним методом (я имею в виду функциональный интерфейс), вы можете заменить его лямбда-выражением. Такие как:
источник