您的位置:首页技术文章
文章详情页

java - 使用lambda表达式(匿名内部类)传参是否有性能问题?

【字号: 日期:2024-01-08 15:02:16浏览:53作者:猪猪

问题描述

编程有一条原则如下:

避免创建不必要的对象:最好能重用对象,而不要在每次需要的时候就创建一个相同功能的新对象。

请看如下代码:

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表达式吗

问题解答

回答1:

首先回答你的问题:是不是每次排序都创建了一个新的Comparator对象,导致性能降低?那么还主张使用Lambda表达式吗?不是,主张

根本原因Lamdba表示根本就不是匿名内部类的语法糖,也就是说Lambda表达式底层实现不是匿名内部类的实现方式,他们其实两个东西

怎么证明呢? 匿名内部类其实在编译的时候会生成一个类文件,命名以ClassName$数字的方式,所以要是Lamdba表达式底层也是由匿名内部类的方式实现的话,那肯定也会生成一个同样类似的内文件 所以我们简单把你的例子分别写在不同包下面的类,再在来检查编译后的效果 匿名内部类实现 InnerTest

java - 使用lambda表达式(匿名内部类)传参是否有性能问题? 这是class文件,可以看到有两个

java - 使用lambda表达式(匿名内部类)传参是否有性能问题?

lambda表达式 LamdbaTest

java - 使用lambda表达式(匿名内部类)传参是否有性能问题?

然而class文件只有一个

java - 使用lambda表达式(匿名内部类)传参是否有性能问题? 所以真相只有一个,哈哈,很显然,这根本就不是一个东西嘛

那Lamdba表达式是怎么实现的? 我们可以来看看他们的字节码,这样骨子里的不一样就完全展示出来了 InnerTest java - 使用lambda表达式(匿名内部类)传参是否有性能问题? LamdbaTest

java - 使用lambda表达式(匿名内部类)传参是否有性能问题?

可以看到两者使用的指令都是不一样的,Lamdba表达式在解析时,使用的是Java7新增的invokedynamic指令,如果你熟悉你这个指令的话,那就可能瞬间明白了,不熟悉的话,你可以问问度娘 不过你可以直接从这个指令名字体会出:动态调用 因此,其实不同于匿名内部类被编译成一个类文件,Lamdba表达式是被编译成了一个静态方法,我们-p可以再看一次就知道了,生成的方法名叫lambda$main$0

java - 使用lambda表达式(匿名内部类)传参是否有性能问题?

所以结合之前两个反编译的结果可以看到,lamdba表达式运行整体思路大致如下 1. lamdba表达式被编译生成当前类的一个私有静态方法 2. 在原调用Lamdba方法的地方编译成了一个invokedynamic指令调用,同时呢也生成了一个对应的BootstrapMethod 3. 当lamdba表达式被JVM执行,也就是碰到2中说到的invokedynamic指令,该指令引导调用LambdaMetafactory.metafactory方法,该方法返回一个CallSite实例 4. 而这个CallSite实例中的target对象,也就是直接引用到一个MethodHandle实例,而这个MethodHandle实例会调用到1中生成的静态方法,在上面的例子就是`lambda$main$0`这个方法,完成整个lamdba表达式的使用

再说一句 其实可以看到lamdba表达式在某种意义上的确比匿名内部类好很多,无论是性能,可读性还是大势~哈哈,我要说大势,是因为lamdba表达式后续可以优化的空间更广,反正我是在java中用惯了,相当喜欢

回答2:

每次排序并不会创建一个新的 Comparator 对象,一般情况下 Lambda 表达式对应的实例(instance)一旦在内存中产生,那么 JVM 在当前环境下会重复使用这个实例。具体的说明,可以参考这个链接:Run-Time Evaluation of Lambda Expressions

在可以提升程序可读性和开发效率的前提下,主张使用 Lambda 表达式

回答3:

可以静态声明一个Lambda表达式内部匿名类对象;

朝生夕灭的小对象对JVM来说不是大问题;

标签: java
相关文章: