web-dev-qa-db-fra.com

À quoi sert l'interface fonctionnelle dans Java 8?

Je suis tombé sur un nouveau terme nommé Interface fonctionnelle dans Java 8.

Je ne pouvais trouver qu'une seule utilisation de cette interface lorsque je travaillais avec des expressions lambda .

Java 8 fournit des interfaces fonctionnelles intégrées et si nous voulons définir une interface fonctionnelle, nous pouvons utiliser l'annotation @FunctionalInterface. Cela nous permettra de déclarer une seule méthode dans l'interface.

Par exemple:

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

A-t-il une utilité dans Java 8 autre que de travailler uniquement avec des expressions lambda ?

La question ici est différente de celle que j'ai posée. Il demande pourquoi nous avons besoin d'une interface fonctionnelle lorsque nous travaillons avec une expression Lambda. Ma question est la suivante: pourquoi utiliser une interface fonctionnelle autre que directement avec des expressions lambda ?

137
Madhusudan

L'annotation @FunctionalInterface est utile pour la vérification du temps de compilation de votre code. Vous ne pouvez pas avoir plus d'une méthode à part static, default et des méthodes abstraites qui surchargent les méthodes dans Object de votre @FunctionalInterface ou de toute autre interface utilisée comme interface fonctionnelle.

Mais vous pouvez utiliser lambdas sans cette annotation et redéfinir des méthodes sans annotation @Override.

De docs

une interface fonctionnelle a exactement une méthode abstraite. Les méthodes par défaut ayant une implémentation, elles ne sont pas abstraites. Si une interface déclare une méthode abstraite substituant l'une des méthodes publiques de Java.lang.Object, cela ne compte pas non plus dans le nombre de méthodes abstraites de l'interface car toute implémentation de l'interface aura une implémentation de Java.lang.Object ou autre.

Ceci peut être utilisé dans l'expression lambda:

public interface Foo {
  public void doSomething();
}

Ceci ne peut pas être utilisé dans l'expression lambda:

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

Mais cela donnera erreur de compilation:

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

Annotation '@FunctionalInterface' non valide; Foo n'est pas une interface fonctionnelle

120
Sergii Bishyr

Le documentation fait en effet une différence entre le but

Un type d'annotation informatif utilisé pour indiquer qu'une déclaration de type d'interface est censée être une interface fonctionnelle telle que définie par la spécification de langage Java.

et le cas d'utilisation

Notez que des instances d'interfaces fonctionnelles peuvent être créées avec des expressions lambda, des références de méthodes ou des références de constructeurs.

dont la formulation n’empêche pas d’autres cas d’utilisation en général. Puisque le but principal est d'indiquer une interface fonctionnelle, votre question actuelle se résume à "Existe-t-il d'autres cas d'utilisation pour interfaces fonctionnelles autres que les expressions lambda et la méthode/références du constructeur? ”

Puisque interface fonctionnelle est une construction de langage Java définie par la spécification de langage Java, seule cette spécification peut répondre à la question suivante:

JLS §9.8. Interfaces fonctionnelles :

En plus du processus habituel de création d'une instance d'interface en déclarant et en instanciant une classe (§15.9), des instances d'interfaces fonctionnelles peuvent être créées avec des expressions de référence de méthode et des expressions lambda (§15.13, §15.27).

Ainsi, la spécification de langage Java ne dit pas le contraire, le seul cas d'utilisation mentionné dans cette section est la création d'instances d'interface avec des expressions de référence de méthode et des expressions lambda. (Cela inclut les références de constructeur car elles sont notées comme une forme d'expression de référence de méthode dans la spécification).

Donc, dans une phrase, non, il n’ya pas d’autre cas d’utilisation dans Java 8.

12
Holger

Pas du tout. Les expressions lambda sont le seul et unique point de cette annotation.

10
Louis Wasserman

Comme d'autres l'ont dit, une interface fonctionnelle est une interface qui expose une méthode. Il peut avoir plus d'une méthode, mais toutes les autres doivent avoir une implémentation par défaut. La raison pour laquelle on l'appelle une "interface fonctionnelle" est parce qu'elle agit efficacement en tant que fonction. Étant donné que vous pouvez passer les interfaces en tant que paramètres, cela signifie que les fonctions sont désormais des "citoyens de premier plan", comme dans les langages de programmation fonctionnels. Cela présente de nombreux avantages et vous en verrez beaucoup lorsque vous utilisez l’API Stream. Bien sûr, les expressions lambda en sont la principale utilisation évidente.

9
Sina Madani

Une expression lambda peut être affectée à un type d'interface fonctionnelle, mais il en va de même pour les références de méthode et les classes anonymes.

Une bonne chose à propos des interfaces fonctionnelles spécifiques dans Java.util.function est qu’elles peuvent être composées pour créer de nouvelles fonctions (comme Function.andThen et Function.compose, Predicate.and, etc.) en raison de la méthodes par défaut pratiques qu'ils contiennent.

5
Hank D

Une interface avec une seule méthode abstraite est appelée interface fonctionnelle. Il n’est pas obligatoire d’utiliser @FunctionalInterface, mais il est recommandé de l’utiliser avec des interfaces fonctionnelles pour éviter d’ajouter accidentellement des méthodes supplémentaires. Si l'interface est annotée avec l'annotation @FunctionalInterface et que nous essayons d'avoir plus d'une méthode abstraite, elle génère une erreur du compilateur.

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;
        }
    }
4
Akhilesh

Vous pouvez utiliser lambda dans 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");
}

Pour plus d'informations sur Java Lambdas et FunctionalInterfaces

2
Websterix

@FunctionalInterface est une nouvelle annotation publiée avec Java 8 et fournit des types de cible pour les expressions lambda. Elle est utilisée lors de la vérification du code de votre temps de compilation.

Quand vous voulez l'utiliser:

1- Votre interface ne doit pas avoir plus d'une méthode abstraite, sinon une erreur de compilation sera donnée.

1- Votre interface Should doit être pure, ce qui signifie que l'interface fonctionnelle est destinée à être implémentée par des classes sans état, par exemple, pure est Comparator interface car elle ne dépend pas de l'état de mise en œuvre, dans ce cas Non erreur de compilation sera donnée, mais dans de nombreux cas, vous ne pourrez pas utiliser lambda avec ce type d'interfaces

Le paquetage Java.util.function contient diverses interfaces fonctionnelles d'usage général telles que Predicate, Consumer, Function et Supplier.

Notez également que vous pouvez utiliser lambdas sans cette annotation.

2
Ahmad Al-Kurdi

Outre d’autres réponses, je pense que la raison principale de "pourquoi utiliser une interface fonctionnelle autre que directement avec des expressions lambda" peut être liée à la nature du langage Java qui est orienté objet.

Les principaux attributs des expressions Lambda sont les suivants: 1. Ils peuvent être transmis autour de 2. et ils peuvent être exécutés ultérieurement dans un temps spécifique (plusieurs fois). Maintenant, pour prendre en charge cette fonctionnalité dans les langues, certaines langues traitent simplement de cette question.

Par exemple, dans Java Script, une fonction (fonction anonyme ou littéral de fonction) peut être adressée en tant qu'objet. Donc, vous pouvez les créer simplement et également les affecter à une variable, etc. Par exemple:

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

ou via ES6, vous pouvez utiliser une fonction de flèche.

const myFunction = ... => ...

Jusqu'à présent, les concepteurs de langages Java n'avaient pas accepté de traiter les fonctionnalités mentionnées de cette manière (techniques de programmation fonctionnelle). Ils croient que le langage Java est orienté objet et qu'ils doivent donc résoudre ce problème via des techniques orientées objet. Ils ne veulent pas manquer de simplicité et de cohérence dans le langage Java.

Par conséquent, ils utilisent des interfaces, par exemple, lorsqu'un objet d'une interface avec une seule méthode (je veux dire une interface fonctionnelle) est nécessaire, vous pouvez le remplacer par une expression lambda. Tel que:

ActionListener listener = event -> ...;
1
MMKarami

Interface fonctionnelle:

  • Introduit dans Java 8
  • Interface qui contient une méthode "single abstract".

Exemple 1:

   interface CalcArea {   // --functional interface
        double calcArea(double rad);
    }           

Exemple 2:

interface CalcGeometry { // --functional interface
    double calcArea(double rad);
    default double calcPeri(double rad) {
        return 0.0;
    }
}       

Exemple 3:

interface CalcGeometry {  // -- not functional interface
    double calcArea(double rad);
    double calcPeri(double rad);
}   

Annotation Java8 - @FunctionalInterface

  • Annotation vérifie que l'interface ne contient qu'une seule méthode abstraite. Sinon, déclenchez une erreur.
  • Même si @FunctionalInterface est manquant, il s'agit toujours d'une interface fonctionnelle (si la méthode est abstraite). L'annotation permet d'éviter les erreurs.
  • L'interface fonctionnelle peut avoir des méthodes statiques et par défaut supplémentaires.
  • par exemple. Itérable <>, Comparable <>, Comparateur <>.

Applications de l'interface fonctionnelle:

  • Références de méthode
  • Expression Lambda
  • Références constructeurs

Pour apprendre les interfaces fonctionnelles, apprendre les premières méthodes par défaut dans l'interface, et après l'apprentissage de l'interface fonctionnelle, il vous sera facile de comprendre la référence de la méthode et l'expression lambda

1
Ketan