Definición precisa de “interfaz funcional” en Java 8

Recientemente comencé a explorar Java 8 y no puedo entender el concepto de “interfaz funcional” que es esencial para la implementación de expresiones lambda de Java. Hay una guía bastante completa de las funciones de lambda en Java, pero me atasqué en el capítulo que da definición al concepto de interfaces funcionales . La definición dice:

Más precisamente, una interfaz funcional se define como cualquier interfaz que tiene exactamente un método abstracto.

Luego procede a ejemplos, uno de los cuales es la interfaz del Comparator :

 public interface Comparator { int compare(T o1, T o2); boolean equals(Object obj); } 

Pude probar que puedo usar una función lambda en lugar del argumento Comparator y funciona (es decir, Collections.sort(list, (a, b) -> ab) ).

Pero en la interfaz de compare métodos de compare e equals son abstractos, lo que significa que tiene dos métodos abstractos . Entonces, ¿cómo puede funcionar esto, si la definición requiere una interfaz para tener exactamente un método abstracto ? ¿Que me estoy perdiendo aqui?

Desde la misma página a la que vinculó :

La interfaz Comparador es funcional porque aunque declara dos métodos abstractos, uno de estos equivalentes tiene una firma correspondiente a un método público en Object. Las interfaces siempre declaran métodos abstractos correspondientes a los métodos públicos de Object, pero generalmente lo hacen implícitamente. Ya sea implícita o explícitamente declarado, tales métodos están excluidos del recuento.

Realmente no puedo decirlo mejor.

Editar: actualizado al texto más reciente de esta página, según el comentario de Maurice (¡gracias!)

Otra explicación se da en la página @FunctionalInterface :

Conceptualmente, 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.

Puede probar qué interfaz es una interfaz funcional correcta utilizando @FunctionalInterface .

P.ej:

  • esto funciona

     @FunctionalInterface public interface FunctionalInterf { void m(); boolean equals(Object o); } 
  • esto genera un error:

     @FunctionalInterface public interface FunctionalInterf { void m(); boolean equals(); } 

    Múltiples métodos abstractos que no se anulan encontrados en la interfaz FunctionalInterf

P. Pero en la interfaz del Comparador los métodos compare () y equals () son abstractos, lo que significa que tiene dos métodos abstractos. Entonces, ¿cómo puede funcionar esto, si la definición requiere una interfaz para tener exactamente un método abstracto? ¿Que me estoy perdiendo aqui?

A.

Una interfaz funcional puede especificar cualquier método público definido por Object, como equals (), sin afectar su estado de “interfaz funcional”. Los métodos de objetos públicos se consideran miembros implícitos de una interfaz funcional porque se implementan automáticamente mediante una instancia de una interfaz funcional.

Los documentos de Java dicen:

Tenga en cuenta que siempre es seguro no anular Object.equals (Object). Sin embargo, anular este método puede, en algunos casos, mejorar el rendimiento al permitir que los progtwigs determinen que dos comparadores distintos imponen el mismo orden.

¿Quizás Comparator es especial? Quizás, a pesar de que es una interfaz, de alguna manera hay una implementación predeterminada de equals() que llama a compare() ? Algorítmicamente, es trivial.

Pensé que todos los métodos que se declararon en las interfaces eran abstractos (es decir, no hay implementación predeterminada). Pero tal vez me estoy perdiendo algo.

Definición:

Si una interfaz contiene solo un método abstracto, dicho tipo de interfaz se denomina interfaz funcional.

Uso:

  1. Una vez que escribimos la expresión Lambda “->” para invocar su funcionalidad, entonces en este contexto necesitamos una interfaz funcional.
  2. Podemos usar la referencia de la interfaz funcional para referir la expresión Lambda.
  3. Dentro de la interfaz funcional podemos tener un método abstracto y n cantidad de métodos predeterminados / estáticos.

Interfaz funcional con respecto a la herencia:

Si una interfaz amplía la interfaz funcional y la interfaz hija no contiene ningún método abstracto, entonces la interfaz hija también se considera interfaz funcional.

La interfaz funcional no es nueva en java, ya se usa en las siguientes interfaces API:

  1. Runnable: contiene solo el método run ().
  2. Llamable: contiene solo el método call ().
  3. Comparable: contiene el método compareTo () solamente.

Antes de Java 8, una interfaz solo podía declarar uno o más métodos también conocidos como Método abstracto (método sin implementación, solo la firma). A partir de Java 8, una interfaz también puede tener implementación de uno o más métodos (conocido como Método predeterminado de interfaz) y métodos estáticos junto con métodos abstractos. Los métodos predeterminados de interfaz se marcan como palabra clave predeterminada.

Entonces la pregunta es, ¿qué es la interfaz funcional? Una interfaz con Single Abstract Method (SAM) se llama Functional Interface.

Lo que significa –

  1. Una interfaz con Single Abstract Method es una interfaz funcional
  2. Una interfaz con el método abstracto simple y cero o más métodos predeterminados y cero o más método estático también es una interfaz funcional válida.

Más detalles con el código de ejemplo https://readtorakesh.blogspot.com/2018/08/functional-interface-java8.html