Interface fonctionnelle et expressions Lambda en Java
Interface fonctionnelle
Une interface fonctionnelle est une interface qui ne contient qu'une seule méthode abstraite. Ils ne peuvent avoir qu'une seule fonctionnalité à exposer.
À partir de Java 8, les expressions lambda peuvent être utilisées pour représenter l'instance d'une interface fonctionnelle. Une interface fonctionnelle peut avoir un nombre quelconque de méthodes par défaut.
Runnable, ActionListener, Comparable sont quelques exemples d’interfaces fonctionnelles.
Annotation @FunctionalInterface
L’annotation @FunctionalInterface est utilisée pour s’assurer que l’interface fonctionnelle ne peut pas avoir plus d’une méthode abstraite. Si plusieurs méthodes abstraites sont présentes, le compilateur signale un message "Unexpected @FunctionalInterface annotation". Cependant, il n'est pas obligatoire d'utiliser cette annotation.
@FunctionalInterface interface Forme { int calculer(int x); }
Package java.util.function
Le package java.util.function de Java 8 contient de nombreuses interfaces fonctionnelles intégrées telles que
- Predicate: L'interface de prédicat a une méthode abstraite test qui donne une valeur booléenne comme résultat pour l'argument spécifié. Son prototype est :
public interface Predicate { public boolean test(T t); }
- BinaryOperator: L'interface BinaryOperator a une méthode abstraite apply qui prend deux arguments et retourne un résultat du même type. Son prototype est
public interface BinaryOperator { public T apply(T x, T y); }
- Function: L'interface Function a une méthode abstraite apply qui prend l'argument de type T et renvoie un résultat de type R. son prototype est
public interface Function { public R apply(T t); }
Comme nous savons qu'une interface fonctionnelle n'a qu'une méthode, il ne devrait pas être nécessaire de définir le nom de cette méthode lors de sa transmission en tant qu'argument. L'expression lambda nous permet de faire exactement cela.
Expressions Lambda
Les expressions lambda expriment essentiellement des instances d'interfaces fonctionnelles. Les expressions lambda implémentent la seule fonction abstraite et implémentent donc des interfaces fonctionnelles
Les expressions lambda sont ajoutées à Java 8 et fournissent les fonctionnalités ci-dessous.
- Activer pour traiter la fonctionnalité en tant qu'argument de méthode ou code en tant que donnée.
- Une fonction qui peut être créée sans appartenir à aucune classe.
- Une expression lambda peut être transmise comme s'il s'agissait d'un objet et exécutée à la demande.
Comment définir l'expression lambda
L'expression lambda introduit un nouvel élément de syntaxe et un nouvel opérateur en langage Java. Le nouvel opérateur est appelé opérateur lambda ou opérateur flèche (->).
Syntaxe :
(liste d'arguments) -> { corps lambda }
Écrivons une méthode simple qui renvoie simplement une valeur double constante.
Exemple 1 :
double getPi() { return 3.1415; }
L'expression lambda équivalente pour la méthode ci-dessus est:
Exemple 2 :
() -> 3.1415
Dans l'expression lambda, le côté gauche de l'expression spécifie les paramètres requis par l'expression (arguments de la méthode), tandis que le côté droit correspond au corps lambda, qui spécifie l'action de l'expression lambda.
Si corps lambda est un bloc de code, vous devez toujours retourner une valeur explicite. Mais, si corps lambda est juste une expression, déclaration de retour n'est pas nécessaire.
Exemple 3 :
() -> { double pi = 3.1415; return pi; }
Comme mentionné précédemment, l'expression lambda n'est pas exécutée seule. Au contraire, elle constitue la mise en oeuvre de la méthode abstraite définie par l'interface fonctionnelle.
Exemple 4 :
@FunctionalInterface interface Forme { int calculer(int x); } public class Test { public static void main(String args[]) { // nous affectons l'expression lambda à // l'instance de l'interface fonctionnelle Forme s = (int x) -> x * x; int ans = s.calculer(5); System.out.println(ans); } }
Exemple 5 :
@FunctionalInterface interface FuncInterface { void methAbstraite(int x); // Default méthode default void methodeDefault() { System.out.println("Hello"); } } public class Test { public static void main(String args[]) { // nous affectons l'expression lambda à // l'instance de l'interface fonctionnelle FuncInterface s = (int x) -> System.out.println(2 * x); s.methAbstraite(5); s.methodeDefault(); } }
Hello
Exemple 6 :
import java.util.Arrays; @FunctionalInterface interface TabOperation { // méthode abstraite pour inverser les éléments d'un tableau int[] inverser(int[] x); } public class Test { public static void main(String args[]) { int[] T = { 3, 5, 7, 8 }; // nous affectons l'expression lambda à // l'instance de l'interface fonctionnelle TabOperation TabOperation tab = (int[] Tab) -> { int Taille = Tab.length; int[] inv = new int[Taille]; for (int i = 0; i < Taille; i++) { inv[i] = Tab[(Taille - i) - 1]; } return inv; }; int[] T2 = tab.inverser(T); System.out.println(Arrays.toString(T2)); } }
Exemple 7 :
import java.util.Arrays; @FunctionalInterface interface fonctionnelle< > { T somme(T a, T b); } public class Test { public static void main(String args[]) { fonctionnelle< Integer> addition = (a, b) -> a + b; System.out.println(" 5 + 4 = " + addition.somme(5, 4)); } }