Java8 Lambdas vs classes anonymes
depuis que Java8 a été récemment publié et que ses nouvelles expressions lambda semblent être vraiment cool, je me demandais si cela signifiait la disparition des classes anonymes auxquelles nous étions tellement habitués.
j'ai fait quelques recherches à ce sujet et j'ai trouvé quelques exemples cool sur la façon dont les expressions Lambda vont systématiquement remplacer ces classes, comme la méthode de tri de la Collection, qui a utilisé pour obtenir une instance anonyme de Comparateur pour effectuer le tri:
Collections.sort(personList, new Comparator<Person>(){
public int compare(Person p1, Person p2){
return p1.firstName.compareTo(p2.firstName);
}
});
peut maintenant être fait en utilisant Lambdas:
Collections.sort(personList, (Person p1, Person p2) -> p1.firstName.compareTo(p2.firstName));
et semble étonnamment concis. Donc ma question Est, y a-t-il une raison de continuer à utiliser ces cours dans Java8 au lieu de Lambdas?
MODIFIER
même question mais dans la direction opposée, quels sont les avantages D'utiliser Lambdas au lieu de classes anonymes, puisque Lambdas ne peut être utilisé avec des interfaces de méthode simple, est cette nouvelle fonctionnalité n'est qu'un raccourci utilisé dans quelques cas ou est-elle vraiment utile?
5 réponses
une classe interne anonyme (AIC) peut être utilisée pour créer une sous-classe d'une classe abstraite ou d'une classe concrète. Un AIC peut également fournir une mise en œuvre concrète d'une interface, y compris l'ajout de state (fields). Une instance D'un AIC peut être désignée en utilisant this
dans ses corps de méthode, de sorte que d'autres méthodes peuvent être appelées sur elle, son état peut être muté au fil du temps, etc. Aucun de ceux-ci ne s'applique à lambdas.
je suppose que la majorité des utilisations de AICs étaient de fournir des implémentations apatrides de fonctions simples et peut donc être remplacé par des expressions lambda, mais il ya d'autres utilisations de AICs pour laquelle lambdas ne peut pas être utilisé. AICs sont ici pour rester.
mise à JOUR
une autre différence entre les expressions AICS et lambda est que les AICs introduisent une nouvelle portée. C'est-à-dire que les noms sont résolus à partir des superclasses et des interfaces de L'AIC et peuvent suivre les noms qui se produisent dans le lexcially environnement environnant. Pour lambdas, tous les noms sont résolus lexicalement.
Lambdas bien qu'un grand trait, ne fonctionnera qu'avec les types SAM. C'est en interface avec une seule méthode abstraite. Il échouerait dès que votre interface contient plus de 1 méthode abstraite. C'est là que les cours anonymes seront utiles.
donc, non nous ne pouvons pas simplement ignorer les cours anonymes. ET POUR INFO, votre méthode sort()
peut être simplifiée, en sautant la déclaration de type pour p1
et p2
:
Collections.sort(personList, (p1, p2) -> p1.firstName.compareTo(p2.firstName));
vous pouvez également utiliser la référence de méthode ici. Soit vous ajoutez une méthode compareByFirstName()
dans la classe Person
et utilisez:
Collections.sort(personList, Person::compareByFirstName);
ou, ajouter un getter pour firstName
, obtenir directement le Comparator
de Comparator.comparing()
méthode:
Collections.sort(personList, Comparator.comparing(Person::getFirstName));
Lambda performance avec Anonyme classes
Lorsque l'application est lancée chaque fichier de classe doit être chargé et vérifiées.
les classes anonymes sont traitées par le compilateur comme un nouveau sous-type pour la classe ou l'interface donnée, il sera donc généré un nouveau fichier de classe pour chacun.
Lambdas sont différents à la génération bytecode, ils sont plus efficaces, utilisé invokedynamic instruction qui vient avec JDK7.
pour Lambdas cette instruction est utilisée pour retarder la traduction de l'expression lambda en bytecode untill runtime. (instruction ne sera invoquée que pour la première fois)
comme résultat L'expression Lambda deviendra une méthode statique(créée à l'exécution). (Il y a une petite différence avec stateles et statefull cas, ils sont peut être résolu par la méthode de génération d'arguments)
il y a les différences suivantes:
1) syntaxe
les expressions Lambda a l'air soigné, comparativement à Anonyme Intérieur de la Classe (AIC)
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("in run");
}
};
Thread t = new Thread(r);
t.start();
}
//syntax of lambda expression
public static void main(String[] args) {
Runnable r = ()->{System.out.println("in run");};
Thread t = new Thread(r);
t.start();
}
2)Champ d'application
une classe interne anonyme est une classe, ce qui signifie qu'elle a une portée pour variable définie à l'intérieur de la classe interne.
attendu que, lambda expression est pas une portée de son propre, mais qui fait partie du cadre englobant.
une règle similaire s'applique pour super et ce mot-clé lorsqu'on utilise la classe intérieure anonyme et l'expression lambda. Dans le cas de la classe interne anonyme ce mot-clé se réfère à la portée locale et le mot-clé super se réfère à la classe super de la classe anonyme. Tandis que dans le cas de l'expression lambda ce mot-clé se réfère à l'objet du type d'enclos et super se réfère à la super classe de la classe qui l'entoure.
//AIC
public static void main(String[] args) {
final int cnt = 0;
Runnable r = new Runnable() {
@Override
public void run() {
int cnt = 5;
System.out.println("in run" + cnt);
}
};
Thread t = new Thread(r);
t.start();
}
//Lambda
public static void main(String[] args) {
final int cnt = 0;
Runnable r = ()->{
int cnt = 5; //compilation error
System.out.println("in run"+cnt);};
Thread t = new Thread(r);
t.start();
}
3) Performances
à l'exécution les classes internes anonymes nécessitent le chargement de la classe, l'allocation de la mémoire et l'initialisation de l'objet et l'invocation d'une méthode non statique tandis que l'expression lambda est une pure activité de temps de compilation et n'entraînent pas de coût supplémentaire pendant l'exécution. Ainsi, la performance de l'expression lambda est meilleure que celle des classes intérieures anonymes.**
**, je me rends compte que ce point n'est pas entièrement vrai . Veuillez vous reporter à la question suivante pour plus de détails. Lambda vs anonymous inner class performance: reducing the loader?
Lambda en java 8 a été introduit pour la programmation fonctionnelle. Où vous pouvez éviter le code boilerplate. J'ai trouvé un article intéressant sur lambda.
http://radar.oreilly.com/2014/04/whats-new-in-java-8-lambdas.html
il est conseillé d'utiliser les fonctions lambda pour des logiques simples. Si la mise en œuvre de la logique complexe en utilisant lambdas sera un overhead dans le débogage du code en cas de problème.