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
interfacetiene semántica de lenguaje de programación, por ejemplo,AutoClosableoIterable(es poco probable que ocurra para sus propias interfaces) - No se espera que la
interfacetenga 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óndefaultparagetTypeName()ser inútil para implementaciones lambda como confiar entoString()) Las instancias de esta
interfacedeben tener una identidad, por ejemplo,java.net.ProtocolFamily,java.nio.file.WatchEvent.Modifier, etc. Tenga en cuenta que estas son implementadas típicamente por unaenumOtro ejemplo es
java.time.chrono.Eraque tiene un solo métodoabstract, pero su especificación dice "Las instancias deErapodrían compararse utilizando el operador==".- La
interfacetiene la intención de alterar el comportamiento de una operación para la cual una implementación de lainterfacesin 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:ActiveEventdebe ser implementado por unAWTEvent,PrinterGraphicsby aGraphics, lo mismo se aplica ajava.awt.print.PrinterGraphics(hey, twointerfaces para exactamente lo mismo ...), wherasjavax.print.FlavorExceptiondebe implementarse mediante una subclasejavax.print.PrintException - No sé si las distintas interfaces del detector de eventos no están marcadas con
@FunctionalInterfacepara 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
interfacesi 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&ThreadFactoryno sería tan malo como@FunctionalInterfacepero no tengo idea de si, por ejemplo,java.security.spec.ECFieldhace 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 unainterfaceparticularinterfaceque 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
@FunctionalInterfacecomo un mensaje de que unainterfaceestá 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 cadainterfacemétodo abstracto usando una expresión lambda, pero cuando la anotación está presente, se asegurará de que pueda usar estainterfacede 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.