web-dev-qa-db-fra.com

Une expression lambda est-elle quelque chose de plus qu'une classe interne anonyme avec une seule méthode?

Il y a un nouveau battage médiatique avec les expressions lambda tant attendues dans Java 8; tous les 3 jours, un autre article apparaît avec eux sur leur cool.

Pour autant que j'ai compris, une expression lambda n'est rien de plus qu'une classe interne anonyme avec une seule méthode (au moins au niveau du code octet). En plus de cela, il est livré avec une autre inférence de type fonctionnalité Nice, mais je pense que l'équivalent de cela peut être obtenu avec des génériques à un certain niveau (bien sûr pas d'une manière aussi soignée qu'avec les expressions lambda).

Sachant cela, les expressions lambda vont-elles apporter plus qu'un simple sucrage syntaxique en Java? Puis-je créer des classes plus puissantes et flexibles ou d'autres constructions orientées objet avec des expressions lambda qui ne peuvent pas être construites avec les fonctionnalités de langage actuelles?

40
m3th0dman

tl; dr: alors que c'est principalement du sucre syntaxique, cette syntaxe plus agréable rend beaucoup de choses pratiques qui se terminaient sans fin, lignes d'accolades et de parenthèses illisibles.

Eh bien, c'est en fait l'inverse, car les lambdas sont beaucoup plus anciens que Java. Les classes internes anonymes avec une seule méthode sont (étaient) les plus proches Java est venu à lambdas. C'est une approximation qui était "assez bonne" pendant un certain temps, mais a une syntaxe très désagréable.

En surface, Java 8 lambdas ne semblent pas être beaucoup plus que du sucre syntaxique, mais quand vous regardez en dessous de la surface, vous voyez des tonnes d'abstractions intéressantes. Par exemple, la spécification JVM traite un lambda assez différemment d'un "vrai" objet, et bien que vous puissiez les gérer comme s'ils contenaient des objets, la JVM n'est pas tenue de les implémenter en tant que tels.

Mais alors que toute cette ruse technique est intéressante et pertinente (car elle permet de futures optimisations dans la JVM!), L'avantage réel est "juste" le sucre syntaxique partie.

Quoi de plus facile à lire:

myCollection.map(new Mapper<String,String>() {
  public String map(String input) {
    return new StringBuilder(input).reverse().toString();
  }
});

ou:

myCollection.map(element -> new StringBuilder(element).reverse().toString());

ou (en utilisant un handle de méthode au lieu d'un lambda):

myCollection.map(String::toUpperCase);

Le fait que vous puissiez enfin exprimer de manière concise ce qui serait auparavant 5 lignes de code (dont 3 totalement ennuyeuses) apporte un réel changement de ce qui est pratique (mais pas de ce qui est possible, accordé).

47
Joachim Sauer

Pour Java, oui, ce n'est rien de plus qu'une meilleure façon de créer une classe interne anonyme. Cela est dû à la décision fondamentale dans Java que chaque bit de code d'octet doit vivre dans une classe spécifique, qui ne peut pas être modifiée maintenant après des décennies de code hérité à considérer.

Cependant, ce n'est pas vraiment ce que sont les expressions lambda. Dans les formalismes où ce sont des concepts natifs plutôt qu'une contorsion rapide, les lambdas sont des éléments fondamentaux; leur syntaxe et l'attitude des gens à leur égard sont très différentes. L'exemple d'une fonction récursive anonyme créée uniquement à partir de lambdas dans Structure et interprétation des programmes informatiques est capable de changer toute votre conception du calcul. (Cependant, je suis à peu près certain que la façon d'apprendre à programmer est simplement ésotérique pour devenir une réussite à succès.)

15
Kilian Foth

Oui, c'est juste un sucre syntaxique, en ce sens que partout où vous écrivez un lambda, vous pouvez réécrire cette expression en tant qu'expression de classe interne anonyme avec une méthode, où la classe implémente l'interface fonctionnelle déduite pour le contexte du lambda, et ce serait exactement équivalent sémantiquement. Et vous pouvez le faire en remplaçant simplement l'expression lambda par l'expression de classe anonyme, sans changer aucune autre expression ou ligne de code.

2
user102008

Joachim Sauer a déjà fait du bon travail pour répondre à votre question, mais n'a fait allusion qu'à quelque chose que je considère important. Puisque Lambdas n'est pas une classe, elles ne sont pas non plus compilées en tant que telles. Toutes les classes internes anonymes entraînent la création d'un fichier .class qui à son tour doit être chargé par le ClassLoader. Donc, utiliser Lambdas à la place ne rend pas seulement votre code plus beau, il réduit également la taille de votre code compilé, l'empreinte mémoire de votre ClassLoader et le temps qu'il faut pour transférer les bits de votre disque dur.