Les expressions lambda ont été introduites dans Java 8 pour un syntaxe plus concise de l'implémentation des interfaces à méthode unique (interfaces fonctionnelles).
Une interface fonctionnelle est une interface avec exactement une méthode abstraite. Exemple :
@FunctionalInterface interface MyAction { void perform(String s); }
Une expression lambda permet d'implémenter cette interface :
MyAction action = (s) -> System.out.println(s); action.perform("Hello lambda!");
Lors de l'utilisation d'une expression lambda, le compilateur comprend automatiquement quelle interface est implémentée (typage ciblé). Les lambdas sont souvent utilisées avec des collections :
List<String> list = Arrays.asList("one", "two", "three"); list.forEach(s -> System.out.println(s));
Question : Une expression lambda peut-elle faire référence à des champs ou méthodes non statiques de la classe externe ? Quelles sont les restrictions à ce sujet ?
Réponse : Une expression lambda peut faire référence aux champs et méthodes de la classe externe, mais si elle utilise des variables locales du méthode externe, ces variables doivent être final ou effectively final (c'est-à-dire ne pas être modifiées après la première assignation). Par exemple :
void doIt() { int x = 42; Runnable r = () -> System.out.println(x); // x doit être effectively final }
Si x est modifié après la déclaration, une erreur de compilation se produira.
Histoire
Lors de l'utilisation d'une lambda à l'intérieur d'une méthode, une tentative de modifier une variable locale externe a entraîné une erreur de compilation "Variable utilisée dans l'expression lambda doit être final ou effectively final". Les développeurs ont passé beaucoup de temps à rechercher la cause, avant de se souvenir de cette restriction.
Histoire
Dans un projet, des interfaces personnalisées étaient utilisées pour les lambdas, mais ils ont oublié de les annoter avec
@FunctionalInterface. Après refactoring, un second méthode a été ajouté à l'interface et le projet a cessé de compiler. Cela a provoqué des erreurs inattendues qui étaient difficiles à détecter.
Histoire
Une tentative de sérialiser un objet contenant un champ avec une expression lambda a conduit à une sérialisation/désérialisation incorrecte - la lambda n'est pas sérialisée par défaut. Il est important de se rappeler que si la lambda contient des dépendances inconsistantes, des erreurs apparaîtront lors de la transmission sur le réseau.