java - what - ¿Por qué no se usa @FunctionalInterface en todas las interfaces en el JDK que califican?
public interface (3)
Bueno, una anotación que documente una intención sería inútil si usted asume que siempre se da esa intención.
Nombró el ejemplo AutoCloseable
que obviamente no está destinado a implementarse como una función, ya que hay Runnable
que es mucho más conveniente para una función con una firma ()->void
. Se pretende que una clase que implementa AutoCloseable
administre un recurso externo que las clases anónimas implementadas a través de la expresión lambda no hacen.
Un ejemplo más claro es Comparable
, una interface
no solo no está pensada para implementarse como una expresión lambda, sino que es imposible implementarla correctamente utilizando una expresión lambda.
Posibles motivos para no marcar una interface
con @FunctionalInterface
por ejemplo:
- La
interface
tiene semántica de lenguaje de programación, por ejemplo,AutoClosable
oIterable
(es poco probable que ocurra para sus propias interfaces) - No se espera que la
interface
tenga implementaciones arbitrarias y / o sea más un identificador que la implementación real, por ejemplo,java.net.ProtocolFamily
, ojava.lang.reflect.GenericArrayType
(Tenga en cuenta que este último también heredará una implementacióndefault
paragetTypeName()
ser inútil para implementaciones lambda como confiar entoString()
) Las instancias de esta
interface
deben tener una identidad, por ejemplo,java.net.ProtocolFamily
,java.nio.file.WatchEvent.Modifier
, etc. Tenga en cuenta que estas son implementadas típicamente por unaenum
Otro ejemplo es
java.time.chrono.Era
que tiene un solo métodoabstract
, pero su especificación dice "Las instancias deEra
podrían compararse utilizando el operador==
".- La
interface
tiene la intención de alterar el comportamiento de una operación para la cual una implementación de lainterface
sin heredar / implementar nada más no tiene sentido, por ejemplo,java.rmi.server.Unreferenced
- Es una abstracción de operaciones comunes de clases que deberían tener más que solo estas operaciones, por ejemplo,
java.io.Flushable
,java.io.Flushable
,java.lang.Readable
- La herencia esperada es parte del contrato y prohíbe las implementaciones de expresiones lambda, por ejemplo, en
java.awt
:ActiveEvent
debe ser implementado por unAWTEvent
,PrinterGraphics
by aGraphics
, lo mismo se aplica ajava.awt.print.PrinterGraphics
(hey, twointerface
s para exactamente lo mismo ...), wherasjavax.print.FlavorException
debe implementarse mediante una subclasejavax.print.PrintException
- No sé si las distintas interfaces del detector de eventos no están marcadas con
@FunctionalInterface
para simetría con otro detector de eventos de múltiples métodos que no pueden ser interfaces funcionales, pero en realidad los oyentes de eventos son buenos candidatos para las expresiones lambda. Si desea eliminar un escucha en un momento posterior, debe almacenar la instancia pero eso no es diferente, por ejemplo, implementaciones de escucha de clase interna. El mantenedor de la biblioteca tiene una base de código grande con más de 200 tipos de candidatos y no los recursos para discutir para cada
interface
si debe anotarse y, por lo tanto, se enfoca en los candidatos principales para ser utilizados en un contexto funcional. Estoy seguro de que, por ejemplo,java.io.ObjectInputValidation
,java.lang.reflect.InvocationHandler
, jucRejectedExecutionHandler
&ThreadFactory
no sería tan malo como@FunctionalInterface
pero no tengo idea de si, por ejemplo,java.security.spec.ECField
hace un buen candidato Cuanto más general sea la biblioteca, es más probable que los usuarios de la biblioteca puedan responder a esa pregunta para unainterface
particularinterface
que estén interesados, pero sería injusto insistir en que el responsable de la biblioteca responda a todas las interfaces.En este contexto, tiene más sentido ver la presencia de un
@FunctionalInterface
como un mensaje de que unainterface
está destinada a ser utilizada junto con las expresiones lambda que a tratar la ausencia de la anotación como un indicador de que no está destinada a ser utilizada. de esta manera. Esto es exactamente como el compilador lo maneja, puede implementar cadainterface
método abstracto usando una expresión lambda, pero cuando la anotación está presente, se asegurará de que pueda usar estainterface
de esta manera.
Java 8 nos dio muchas maneras divertidas de usar interfaces funcionales y con ellas una nueva anotación: @FunctionalInterface . Su trabajo es decirle al compilador que nos grite si no nos atenemos a las reglas de una interfaz funcional (solo un método abstracto que deba anularse).
Hay 43 interfaces en el paquete java.util.function con esta anotación. Una búsqueda de jdk.1.8.0 / src para @FunctionalInterface
solo @FunctionalInterface
57 hits. ¿Por qué las otras interfaces (como AutoCloseable) que podrían haber agregado @FunctionalInterface
aún faltan?
Hay un poco de un vago indicio en la @FunctionalInterface las @FunctionalInterface :
"Un tipo de anotación informativa utilizado para indicar que una declaración de tipo de interfaz pretende ser una interfaz funcional"
¿Hay alguna buena razón para NO tener la intención de que una interfaz que he diseñado (que puede ser simplemente una interfaz funcional) no se use como una? ¿Está dejando de lado una indicación de algo además de no darse cuenta de que podría haber sido agregado?
¿La adición de métodos abstractos a cualquier interfaz publicada no va a perjudicar a nadie que la implemente, funcional o no? Me siento cínico asumiendo que simplemente no se molestaron en cazarlos, pero ¿qué otra explicación hay?
Actualización : Después de revisar "¿Debería ser ''Comparable'' una ''interfaz funcional''?" Me parece que todavía tengo preguntas molestas. Cuando una interfaz de método único y una interfaz funcional son estructuralmente idénticas, ¿qué se deja de ser diferente? ¿Es la diferencia simplemente los nombres? Comparable y Comparator están lo suficientemente cerca semánticamente. Resulta que son diferentes estructuralmente, aunque todavía no es el mejor ejemplo ...
¿Existe un caso en el que una SMI es estructuralmente buena para usar como una interfaz funcional pero aún no se recomienda sobre el significado semántico del nombre de la interfaz y el método? O tal vez el contrato implícito por los Javadocs?
En java 8, la interfaz funcional es una interfaz que tiene exactamente un método abstracto llamado método funcional con el que los parámetros de la expresión lambda y los tipos de retorno coinciden.
El java.util.function
contiene interfaces funcionales de uso general utilizadas por JDK y también disponibles para usuarios finales . Si bien no son el conjunto completo de interfaces funcionales a las que pueden ser aplicables las expresiones lambda, proporcionan el suficiente para cubrir los requisitos comunes. Usted es libre de crear sus propias interfaces funcionales siempre que los conjuntos existentes no sean suficientes.
Hay muchas interfaces disponibles que merecen ser designadas como interfaz funcional, pero el paquete java.util.function
ya proporciona interfaces funcionales para casi todos nuestros propósitos.
Por ejemplo, mira en el siguiente código.
public interface Comparable<T> {
public int compareTo(T o);
}
@FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}
public static void main(String[] args){
ToIntFunction<String> f = str -> Integer.parseInt(str);
Comparable<String> c = str -> Integer.parseInt(str);
}
Comparable
también puede tomar un objeto y obtener algún valor de tipo int, pero se proporciona una interfaz dedicada más general ToIntFunction
para realizar esta tarea. No existe una regla tan @FunctionalInterface
que todas las interfaces que merecen se deben anotar con @FunctionalInterface
pero para obtener la ventaja de la función lambda, la interfaz debe cumplir todos los criterios definidos por FunctionalInterface.
Expansión planificada. El hecho de que una interfaz cumpla con los requisitos de un SMI ahora no significa que la expansión no sea necesaria más adelante.