1 本质
lambda
表达式本质上是对匿名内部类实例的一种简化写法。
1.1 案例
有以下List<Integer>
对象:
List<Integer> list = Arrays.asList(1, 3, 5, 7, 9, 2, 4, 6, 8, 10);
在对List
进行从小大大排序时,会用到List#sort(Comparator)
方法,需要传递实现Comparator
接口的对象作为参数:
default void sort(Comparator<? super E> c) {
// 省略方法体
}
可以想到有如下四种不同的代码编写的方式。
1、 创建Comparator
的实现类#
根据需求,手动实现Comparator
接口:
public class AscComparator implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
}
然后,创建AscComparator
实例,传给List#sort(Comparator)
方法:
Comparator<Integer> ascComparator = new AscComparator();
list.sort(ascComparator);
2、创建Comparator
的匿名对象#
可以直接创建Comparator
的匿名对象,然后传给List#sort(Comparator)
方法:
Comparator<Integer> anonymousComparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};
list.sort(anonymousComparator);
等价于:
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
3、lambda
表达式
直接使用lambda
表达式:
list.sort((o1, o2) -> o1.compareTo(o2));
4、方法引用
使用方法引用(方法引用具体概念和使用可以查看相关文章):
list.sort(Integer::compare);
可以明显看出,使用lambda
表达式和方法引用极大提高了开发的速度,提升了代码的简洁性。
1.2 本质
实际上,lambda
表达式只是JVM提供的语法糖。在JVM执行过程中,会根据lambda
表达式的规则,动态创建出匿名的接口实现类对象。
lambda
表达式本质上是Java对象。
可以通过查看lambda
表达式的Class
对象和实例对象来证明这一点:
public class LambdaExpression {
public void printConsumer(Consumer consumer) {
System.out.println(consumer.getClass());
System.out.println(consumer.getClass().getInterfaces()[0]);
System.out.println(consumer);
}
}
1、案例1#
运行以下代码:
LambdaExpression lambdaObjPrinter = new LambdaExpression();
lambdaObjPrinter.printConsumer(o -> o.getClass());
lambdaObjPrinter.printConsumer(o -> o.getClass());
会有如下输出:
class lambda.LambdaExpression$$Lambda$1/2003749087
interface java.util.function.Consumer
lambda.LambdaExpression$$Lambda$1/2003749087@41629346
class lambda.LambdaExpression$$Lambda$2/1078694789
interface java.util.function.Consumer
lambda.LambdaExpression$$Lambda$2/1078694789@6d311334
- 这证明了执行过程中会根据
lambda
表达式动态生成函数式接口的实现类,并创建该实现类的实例。 - 同时,先后执行的2个
lambda
表达式,尽管格式相同,仍然动态生成了2个实现类。
查看编译后的.class
文件如下:
LambdaExpression lambdaObjPrinter = new LambdaExpression();
lambdaObjPrinter.printConsumer((o) -> {
o.getClass();
});
lambdaObjPrinter.printConsumer((o) -> {
o.getClass();
});
2、案例2
运行如下代码:
LambdaExpression lambdaObjPrinter = new LambdaExpression();
for (int i = 0; i < 2; i++) {
lambdaObjPrinter.printConsumer(o -> o.getClass());
}
System.out.println("=============");
for (int i = 0; i < 2; i++) {
lambdaObjPrinter.printConsumer(o -> o.getClass());
}
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/293974.html