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?

83
demandé sur Amin Abu-Taleb 2014-03-25 18:41:18

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.

82
répondu Stuart Marks 2014-03-27 00:33:16

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));
51
répondu Rohit Jain 2014-03-25 14:58:45

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)

27
répondu Dmitriy Kuzkin 2015-11-23 15:43:02

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?

6
répondu atom217 2017-09-03 15:07:27

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.

3
répondu Tim 2015-08-13 07:35:16