¿Cuál es el uso de la interfaz funcional en Java 8?

Me encontré con un nuevo término llamado Interfaz funcional en Java 8.

Solo pude encontrar un uso de esta interfaz mientras trabajaba con expresiones lambda .

Java 8 proporciona algunas interfaces funcionales integradas y, si queremos definir una interfaz funcional, podemos utilizar la anotación @FunctionalInterface . Nos permitirá declarar solo un único método en la interfaz.

Por ejemplo:

 @FunctionalInterface interface MathOperation { int operation(int a, int b); } 

¿Qué tan útil es en Java 8 además de solo trabajar con expresiones lambda ?

La pregunta aquí es diferente de la que hice. Se pregunta por qué necesitamos la Interfaz funcional mientras trabajamos con la expresión Lambda. Mi pregunta es: ¿por qué usar Functional Interface que no sea directamente con expresiones lambda ?

@FunctionalInterface anotación @FunctionalInterface es útil para verificar el tiempo de comstackción de su código. No puede tener más de un método además de los métodos static , default y abstractos que anulan los métodos en Object en su @FunctionalInterface o cualquier otra interfaz utilizada como interfaz funcional.

Pero puedes usar lambdas sin esta anotación, así como puedes anular los métodos sin la anotación @Override .

De los documentos

una interfaz funcional tiene exactamente un método abstracto. Como los métodos predeterminados tienen una implementación, no son abstractos. Si una interfaz declara un método abstracto que anula uno de los métodos públicos de java.lang.Object, eso tampoco cuenta para el recuento de métodos abstractos de la interfaz, ya que cualquier implementación de la interfaz tendrá una implementación desde java.lang.Object o en otro lugar.

Esto se puede usar en la expresión lambda:

 public interface Foo { public void doSomething(); } 

Esto no se puede usar en la expresión lambda:

 public interface Foo { public void doSomething(); public void doSomethingElse(); } 

Pero esto dará error de comstackción :

 @FunctionalInterface public interface Foo { public void doSomething(); public void doSomethingElse(); } 

Anotación ‘@FunctionalInterface’ inválida; Foo no es una interfaz funcional

Las interfaces funcionales tienen una única funcionalidad para exhibir. Por ejemplo, una interfaz Comparable con un solo método ‘compareTo’ se usa para propósitos de comparación. Java 8 ha definido muchas interfaces funcionales para usar extensivamente en expresiones lambda .

Se ha introducido una anotación: @FunctionalInterface que se puede usar para errores de nivel de comstackción cuando la interfaz que ha anotado no es una interfaz funcional válida.

 @FunctionalInterface interface MathOperation { int operation(int a, int b); } 

Intentemos agregar otro método abstracto:

 @FunctionalInterface interface MathOperation { int operation(int a, int b); int operationMultiply(int a, int b); } 

Arriba se generará un error de comstackción como se indica a continuación:

 Unexpected @FunctionalInterface annotation @FunctionalInterface ^ MathOperation is not a functional interface multiple non-overriding abstract methods found in interface MathOperation 

Una interfaz funcional es válida incluso si se @FunctionalInterface anotación @FunctionalInterface . Es solo para informar al comstackdor que aplique un solo método abstracto dentro de la interfaz.

  interface MathOperation { int operation(int a, int b); } 

Conceptualmente, una interfaz funcional tiene exactamente un método abstracto. Como los métodos predeterminados tienen una implementación, no son abstractos. Como los métodos predeterminados no son abstractos, puede agregar métodos predeterminados a su interfaz funcional tantas veces como desee.

A continuación se muestra una interfaz funcional válida:

 @FunctionalInterface interface MathOperation { int operation(int a, int b); default void doSomeMathOperation(){ //Method body } } 

Si una interfaz declara un método abstracto que anula uno de los métodos públicos de java.lang.Object, eso tampoco cuenta para el recuento de métodos abstractos de la interfaz, ya que cualquier implementación de la interfaz tendrá una implementación desde java.lang.Object o en otro lugar.

Por ejemplo, a continuación hay una interfaz funcional válida a pesar de que declaró dos métodos abstractos. ¿Por qué? Porque uno de estos métodos abstractos “es igual a ()” que tiene la firma igual al método público en la clase Object.

 @FunctionalInterface interface MathOperation { int operation(int a, int b); @Override public String toString(); //Overridden from Object class @Override public boolean equals(Object obj); //Overridden from Object class } 

Si bien el uso previsto de las interfaces funcionales es para expresiones lambda , referencias de métodos y referencias de constructores , todavía se pueden usar, como cualquier interfaz, con clases anónimas, implementadas por clases o creadas por métodos de fábrica.

La documentación hace de hecho una diferencia entre el propósito

Un tipo de anotación informativa utilizado para indicar que una statement de tipo de interfaz está destinada a ser una interfaz funcional tal como se define en la Especificación del lenguaje Java.

y el caso de uso

Tenga en cuenta que las instancias de interfaces funcionales se pueden crear con expresiones lambda, referencias de métodos o referencias de constructores.

cuya redacción no excluye otros casos de uso en general. Dado que el propósito principal es indicar una interfaz funcional , su pregunta real se reduce a “¿Hay otros casos de uso para interfaces funcionales que no sean expresiones lambda y referencias de método / constructor?”

Como la interfaz funcional es una construcción de lenguaje Java definida por la especificación de lenguaje Java, solo esa especificación puede responder esa pregunta:

JLS §9.8. Interfaces funcionales :

Además del proceso habitual de creación de una instancia de interfaz declarando y creando una instancia de una clase (§15.9), se pueden crear instancias de interfaces funcionales con expresiones de referencia de método y expresiones lambda (§15.13, §15.27).

Entonces, la Especificación del lenguaje Java no dice lo contrario, el único caso de uso mencionado en esa sección es el de crear instancias de interfaz con expresiones de referencia de método y expresiones lambda. (Esto incluye referencias de constructor ya que se anotan como una forma de expresión de referencia de método en la especificación).

Entonces en una oración, no, no hay otro caso de uso para ella en Java 8.

De ningún modo. Las expresiones Lambda son el único punto de esa anotación.

Una expresión lambda se puede asignar a un tipo de interfaz funcional, pero también lo pueden hacer las referencias de método y las clases anónimas.

Una cosa buena de las interfaces funcionales específicas en java.util.function es que se pueden componer para crear nuevas funciones (como Function.andThen y Function.compose , Predicate.and , etc.) debido a los prácticos métodos predeterminados que contienen.

Como han dicho otros, una interfaz funcional es una interfaz que expone un método. Puede tener más de un método, pero todos los demás deben tener una implementación predeterminada. La razón por la que se llama una “interfaz funcional” es porque efectivamente actúa como una función. Dado que puede pasar las interfaces como parámetros, significa que las funciones ahora son “ciudadanos de primera clase”, como en los lenguajes de progtwigción funcionales. Esto tiene muchos beneficios, y los verá bastante cuando use Stream API. Por supuesto, las expresiones lambda son el principal uso obvio para ellos.

@FunctionalInterface es una nueva anotación que se lanza con Java 8 y proporciona tipos de destino para expresiones lambda y se usa en la verificación del tiempo de comstackción de su código.

Cuando quieras usarlo:

1- Su interfaz no debe tener más de un método abstracto, de lo contrario se dará error de comstackción.

1- Su interfaz debe ser pura, lo que significa que la interfaz funcional está pensada para ser implementada por clases sin estado, ejemplo de pura es la interfaz del Comparator porque no depende del estado de los implementadores, en este caso no se dará ningún error de comstackción, pero en muchos casos no podrás usar lambda con este tipo de interfaces

El paquete java.util.function contiene varias interfaces funcionales de uso general, como Predicate , Consumer , Function y Supplier .

También tenga en cuenta que puede usar lambdas sin esta anotación.