¿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 cualquier interfaz funcional, podemos hacer uso de la anotación @FunctionalInterface. Nos permitirá declarar solo un método en la interfaz.

Por ejemplo:

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

Lo útil que es en Java 8 que no sea solo ¿trabajando con expresiones lambda?

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

Author: Ahmad Al-Kurdi, 2016-04-27

10 answers

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

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

De docs

Una interfaz funcional tiene exactamente un método abstracto. Desde el valor predeterminado los métodos 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.Objeto, que tampoco cuenta para la interfaz de método abstracto contar ya que cualquier implementación de la interfaz será tener una implementación de java.lang.Objeto 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 lambda expresión:

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

Pero esto dará error de compilación :

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

Anotación '@FunctionalInterface' no válida; Foo no es una anotación funcional interfaz

 92
Author: Sergii Bishyr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-03 04:20:29

Las interfaces funcionales tienen una única funcionalidad para exhibir. Por ejemplo, una interfaz comparable con un único método 'compareTo' se utiliza para fines de comparación. Java 8 ha definido muchas interfaces funcionales para ser usadas extensivamente en expresiones lambda.

Se ha introducido una anotación- @FunctionalInterface que se puede usar para errores a nivel de compilador cuando la interfaz que ha anotado no es una Interfaz Funcional válida.

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

Vamos a tratar de añadir otro método abstracto:

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

Anterior resultará en un error del compilador 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 omite la anotación @FunctionalInterface. Es solo para informar al compilador 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. Dado que los métodos predeterminados tienen una implementación, no son abstractos. Dado que los métodos predeterminados no son abstractos, gratis para agregar métodos predeterminados a su interfaz funcional tantos 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 reemplazando uno de los métodos públicos de java.lang.Objeto, que 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.Objeto o en otro lugar.

Por ejemplo, A continuación se muestra un funcional válido interfaz a pesar de que declaró dos métodos abstractos. ¿Por qué? Porque uno de estos métodos abstractos "equals ()" que tiene firma igual al método público en la clase de objeto.

@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
 }

Mientras que el uso previsto de 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.

 49
Author: Prakash Hari Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-27 14:35:50

La documentación hace realmente una diferencia entre el propósito

Un tipo de anotación informativa utilizado para indicar que una declaración de tipo de interfaz está destinada a ser una interfaz funcional 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étodos/constructores?"

Dado que functional interface es una construcción de lenguaje Java definida por la Especificación del Lenguaje Java, solo esa especificación puede responder a esa pregunta:

JLS §9.8. Interfaces funcionales :

Además del proceso habitual de crear una instancia de interfaz declarando e instanciando 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).

Así que 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étodos y expresiones lambda. (Esto incluye referencias de constructores, ya que se señalan como una forma de expresión de referencia de método en la especificación).

Así que en una oración, no, no hay otro caso de uso para ello en Java 8.

 9
Author: Holger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-27 08:34:19

Para nada. Las expresiones Lambda son el único punto de esa anotación.

 8
Author: Louis Wasserman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-27 06:25:24

Se puede asignar una expresión lambda a un tipo de interfaz funcional, pero también se pueden asignar referencias de métodos y clases anónimas.

Una cosa buena sobre 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.

 5
Author: Hank D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-27 06:46:44

Como otros han dicho, 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 actúa efectivamente como una función. Dado que puede pasar interfaces como parámetros, significa que las funciones ahora son "ciudadanos de primera clase" como en los lenguajes de programación funcionales. Esto tiene muchos beneficios, y los verás bastante cuando uses la transmisión API. Por supuesto, las expresiones lambda son el principal uso obvio para ellas.

 3
Author: Sina Madani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-27 14:39:56

Una interfaz con un solo método abstracto se llama Interfaz Funcional. No es obligatorio usar @FunctionalInterface, pero es una buena práctica usarlo con interfaces funcionales para evitar la adición de métodos adicionales accidentalmente. Si la interfaz está anotada con @FunctionalInterface annotation y tratamos de tener más de un método abstracto, genera un error de compilador.

package com.akhi;
    @FunctionalInterface
    public interface FucnctionalDemo {

      void letsDoSomething();
      //void letsGo();      //invalid because another abstract method does not allow
      public String toString();    // valid because toString from Object 
      public boolean equals(Object o); //valid

      public static int sum(int a,int b)   // valid because method static
        {   
            return a+b;
        }
        public default int sub(int a,int b)   //valid because method default
        {
            return a-b;
        }
    }
 2
Author: Akhilesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-03 09:47:49

@FunctionalInterface es una nueva anotación se lanzan con Java 8 y proporcionar tipos de destino para las expresiones lambda y se utiliza en la comprobación de tiempo de compilació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á un error de compilación.

1-Su interfaz Debe ser pura, lo que significa que la interfaz funcional está destinada a ser implementada por clases sin estado, exmple de pure es Comparator interfaz debido a que no depende del estado del implementador, en este caso No se dará un error de compilación, pero en muchos casos no podrá usar lambda con este tipo de interfaces

El paquete java.util.function contiene varias interfaces funcionales de propósito general tales como Predicate, Consumer, Function, y Supplier.

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

 1
Author: Ahmad Al-Kurdi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-17 17:50:41

Además de otras respuestas, creo que la razón principal de "por qué usar una Interfaz Funcional que no sea directamente con expresiones lambda" puede estar relacionada con la naturaleza del lenguaje Java que está Orientado a Objetos.

Los principales atributos de las expresiones Lambda son: 1. Se pueden pasar alrededor de 2. y se pueden ejecutar en el futuro en un tiempo específico (varias veces). Ahora para apoyar esta característica en idiomas, algunos otros idiomas se ocupan simplemente de este asunto.

Por ejemplo, en Java Script, un la función (función anónima, o literales de función) se puede abordar como un objeto. Por lo tanto, puede crearlos simplemente y también se pueden asignar a una variable y así sucesivamente. Por ejemplo:

var myFunction = function (...) {
    ...;
}
alert(myFunction(...));

O a través de ES6, puede usar una función de flecha.

const myFunction = ... => ...

Hasta ahora, los diseñadores del lenguaje Java no han aceptado manejar las características mencionadas de esta manera (técnicas de programación funcional). Creen que el lenguaje Java está orientado a Objetos y por lo tanto deben resolver este problema a través de Técnicas orientadas a objetos. No quieren perderse la simplicidad y consistencia del lenguaje Java.

Por lo tanto, usan interfaces, como cuando se necesita un objeto de una interfaz con un solo método (me refiero a una interfaz funcional), puede reemplazarlo con una expresión lambda. Tales como:

ActionListener listener = event -> ...;
 1
Author: MMKarami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-14 13:44:00

Puede usar lambda en Java 8

  public static void main(String[] args) {
    tentimes(inputPrm -> System.out.println(inputPrm));
    //tentimes(System.out::println);  // You can also replace lambda with static method reference
    }

    public static void tentimes(Consumer myFunction){
      for(int i = 0; i < 10; i++)
        myFunction.accept("hello");
    }

Para más información sobre Java Lambdas y FunctionalInterfaces

 1
Author: Akiner Alkan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-17 06:06:05