Maison > Questions et réponses > le corps du texte
编程有一条原则如下:
避免创建不必要的对象:最好能重用对象,而不要在每次需要的时候就创建一个相同功能的新对象。
请看如下代码:
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
// 1、匿名内部类
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
//2、lambda表达式
Collections.sort(names, (a, b) -> b.compareTo(a));
是不是每次排序都创建了一个新的Comparator对象,导致性能降低?那么还主张使用Lambda表达式吗?
天蓬老师2017-04-18 10:55:20
Répondez d'abord à votre question :
Un nouvel objet Comparator est-il créé à chaque tri, ce qui entraîne une réduction des performances ? Alors, préconisez-vous toujours d’utiliser des expressions Lambda ?
Non, je préconise
La raison fondamentale
Lamdba signifie qu'il ne s'agit pas du tout de sucre syntaxique pour les classes internes anonymes. C'est-à-dire que l'implémentation sous-jacente de l'expression Lambda n'est pas du tout l'implémentation de classes internes anonymes. Ce sont en fait deux choses
Comment le prouver ?
Les classes internes anonymes généreront en fait un fichier de classe lors de la compilation, nommé avec des numéros ClassName$, donc si la couche inférieure de l'expression Lamdba est également implémentée par des classes internes anonymes, elle générera certainement des fichiers internes similaires
Nous écrivons donc simplement votre exemple dans des classes sous différents packages, puis vérifions l'effet compilé
Une classe interne anonyme implémente InnerTest
Ceci est un fichier de classe, vous pouvez voir qu'il y en a deux
expression lambda LamdbaTest
Cependant, il n'y a qu'un seul fichier de classe
Donc il n'y a qu'une seule vérité, haha, évidemment, ce n'est pas du tout la même chose
Comment l'expression Lamdba est-elle implémentée ?
Nous pouvons jeter un œil à leur bytecode, afin que les différences sous-jacentes soient pleinement démontrées
InnerTest
LamdbaTest
Vous pouvez voir que les instructions utilisées par les deux sont différentes. Lors de l'analyse des expressions Lamdba, la nouvelle instruction Invocationdynamic de Java 7 est utilisée. Si vous connaissez cette instruction, vous pouvez la comprendre instantanément. familier, vous pouvez demander à Du Niang
Mais vous pouvez le comprendre directement à partir du nom de cette commande : Appel dynamique
Par conséquent, contrairement aux classes internes anonymes qui sont compilées dans un fichier de classe, Lamdba L'expression est compilée dans une méthode statique. Nous pouvons le revoir en regardant -p La méthode générée est nommée lambda$main
.
<🎜>所以结合之前两个反编译的结果可以看到,lamdba表达式运行整体思路大致如下
1. lamdba表达式被编译生成当前类的一个私有静态方法
2. 在原调用Lamdba方法的地方编译成了一个invokedynamic指令调用,同时呢也生成了一个对应的BootstrapMethod
3. 当lamdba表达式被JVM执行,也就是碰到2中说到的invokedynamic指令,该指令引导调用LambdaMetafactory.metafactory方法,该方法返回一个CallSite实例
4. 而这个CallSite实例中的target对象,也就是直接引用到一个MethodHandle实例,而这个MethodHandle实例会调用到1中生成的静态方法,在上面的例子就是`lambda$mainrrreee`这个方法,完成整个lamdba表达式的使用
Encore une chose
En fait, vous pouvez voir que les expressions lamba sont en effet bien meilleures que les classes internes anonymes dans un sens, qu'il s'agisse de performances, de lisibilité ou de tendance générale ~ Haha, je veux pour dire tendance générale, car l'expression lamdba peut être optimisée dans un espace plus large. Quoi qu'il en soit, j'ai l'habitude de l'utiliser en java, et j'aime bien
阿神2017-04-18 10:55:20
Chaque tri ne crée pas de nouvel objet Comparator
Généralement, une fois l'instance correspondant à l'expression Lambda générée en mémoire, la JVM sera réutilisée ci-dessous. Pour des instructions spécifiques, veuillez vous référer à ce lien : Évaluation d'exécution des expressions Lambda
En partant du principe que cela peut améliorer la lisibilité du programme et l'efficacité du développement, il est recommandé d'utiliser l'Lambdaexpression
怪我咯2017-04-18 10:55:20
Vous pouvez déclarer statiquement un objet de classe anonyme dans une expression Lambda
Les petits objets qui vont et viennent ne sont pas un gros problème pour la JVM