Ответ 1
Ну, аннотация, документирующая намерение, будет бесполезной, если вы предположите, что всегда есть это намерение.
Вы назвали пример AutoCloseable
, который, очевидно, не предназначен для реализации как функция asres Runnable
, что намного удобнее для функции с ()->void
сигнатурой. Предполагается, что класс, реализующий AutoCloseable
, управляет внешним ресурсом, который анонимные классы, реализованные с помощью выражения лямбда, не делают.
Более понятный пример: Comparable
, interface
не только не предназначен для реализации в качестве лямбда-выражения, но и для его правильной реализации с использованием выражения лямбда.
Возможные причины не маркировать interface
с помощью @FunctionalInterface
на примере:
-
interface
имеет семантику языка программирования, например.AutoClosable
илиIterable
(что вряд ли произойдет для ваших собственных интерфейсов) - Не ожидается, что
interface
имеет произвольные реализации и/или больше идентификатор, чем фактическая реализация, например.java.net.ProtocolFamily
илиjava.lang.reflect.GenericArrayType
(обратите внимание, что последний также наследует реализациюdefault
дляgetTypeName()
, бесполезную для лямбда-реализаций, полагаясь наtoString()
) -
Экземпляры этого
interface
должны иметь идентификатор, например.java.net.ProtocolFamily
,java.nio.file.WatchEvent.Modifier
и т.д. Обратите внимание, что они обычно реализуются с помощьюenum
Другим примером является
java.time.chrono.Era
, который имеет только один методabstract
, но его спецификация говорит:" ЭкземплярыEra
могут сравниваться с помощью оператора==
. -
interface
предназначен для изменения поведения операции, для которой реализацияinterface
без наследования/реализации чего-либо еще не имеет смысла, например.java.rmi.server.Unreferenced
- Это абстракция общих операций классов, которые должны иметь не только эти операции, например.
java.io.Closeable
,java.io.Flushable
,java.lang.Readable
- Ожидаемое наследование является частью контракта и запрещает реализацию лямбда-выражения, например. в
java.awt
:ActiveEvent
должен быть реализован с помощьюAWTEvent
,PrinterGraphics
наGraphics
, то же самое относится кjava.awt.print.PrinterGraphics
(hey, twointerface
для точно такой же вещи...), гдеjavax.print.FlavorException
должен быть реализован подклассомjavax.print.PrintException
- Я не знаю, поддерживает ли различные интерфейсы прослушивателя событий, отмеченные
@FunctionalInterface
для симметрии с другим прослушивателем событий нескольких методов, которые не могут быть функциональными интерфейсами, но на самом деле прослушиватели событий являются хорошими кандидатами для лямбда-выражений. Если вы хотите удалить слушателя позже, вам нужно сохранить экземпляр, но он не отличается от, например. внутренние реализации слушателя. -
У хранителя библиотеки есть большая база кода с более чем 200 типами кандидатов, а не ресурсы для обсуждения для каждого
interface
, следует ли ее аннотировать и, следовательно, основное внимание уделяется основным кандидатам для использования в функциональном контексте. Я уверен, что, например,java.io.ObjectInputValidation
,java.lang.reflect.InvocationHandler
, jucRejectedExecutionHandler
иThreadFactory
не будут плохими, как@FunctionalInterface
, но я не знаю, будет ли, например.java.security.spec.ECField
делает хорошего кандидата. Чем более общей является библиотека, тем более вероятные пользователи библиотеки смогут ответить на этот вопрос для конкретногоinterface
, который им интересен, но было бы несправедливо настаивать на том, чтобы разработчик библиотеки отвечал на него для всех интерфейсов.В этом контексте имеет смысл видеть наличие
@FunctionalInterface
в качестве сообщения о том, чтоinterface
определенно предназначено для использования вместе с лямбда-выражениями, чем рассматривать отсутствие аннотации в качестве индикатора ее не предназначенный для использования таким образом. Это точно так же, как компилятор справляется с этим, вы можете реализовать каждый абстрактный методinterface
с помощью лямбда-выражения, но когда присутствует аннотация, он будет гарантировать, что вы можете использовать этотinterface
таким образом.