首页 时尚 演艺 游戏 八卦 音乐 影视 活动 热点 快讯 聚焦 综合 资讯
当前位置:首页 > 快讯 > 正文

lambda表达式的“脱糖”策略 速看料

2023-01-17 20:36:19    来源:哔哩哔哩

lambda表达式,语法比匿名类简单,可以替代匿名类,那么,lambda表达式到底是不是匿名类的语法糖;或者说lambda表达式编译之后,底层到底变成了什么;它和匿名类中的this关键字意义是否相同。

极客架构师——专注架构师成长。

大家好,我是码农老吴。


(相关资料图)

在前面的视频中,我们分享了策略模式的三次演变,从普通的策略模式,到匿名类的测试模式,再到lambda表达式的策略模式。可以看到,代码一次比一次简单。那么lambda表达式到底是不是匿名类的语法糖呢?这是个面试中,经常被提问的问题,我们需要认真对待。

我们先简要回顾一下前面的代码,然后进行深入分析。

案例-商品过滤

类图

接口及类

SKU:商品实体类

ISKUService:商品服务接口

SKUService:商品服务实现类

IShopService:店铺服务接口

ShopService:店铺服务实现类

ShopServiceTest:店铺服务测试类

SKUService:商品服务实现类

定义了商品过滤的方法,使用了上期分享的JDK内置,函数式接口Predicate。这样我们就不用再定义商品过滤的策略接口。

ShopService:店铺服务实现类

在这个类中,除了searchSku01()使用匿名类实现商品过滤之外,后面三个方法,都是基于lambda表达式实现商品过滤的,之所以要三个方法,是因为三个方法中的lambda表达式,分别代表了一种特殊类型的lambda表达式。下面会详细讲解。

ShopServiceTest:店铺服务测试类

运行结果

Lambda表达式是否有独立的字节码文件

Java语言中的匿名类,出现的非常早,大概在java1.1版本就有了,大家一般都不陌生,众所周知,匿名类在编译之后,都会自动生成一个独立的字节码(class)文件。

文件名的格式是:外部类名$数字.class。

我们看看这个案例,它有几个独立的匿名类class文件。

从下图可以看到,编译器只生成了一个匿名类字节码文件,也就是ShopService$1.class.

反编译匿名类的独立字节码文件

从反编译的文件中,可以看到,ShopService$1.class这个文件确实是我们匿名类里面的内容。它执行了函数式接口Predicate<SKU>,实现了test方法。

而我们使用lambda表达式的代码,并没有生成对应的字节码文件。

这至少从表面上看,lambda表达式,底层并不是匿名类。

我们再看看使用匿名类的方法和使用lambda表达式的方法,各自对应的字节码文件,是否一样。

字节码文件对比

从下图可以看出,使用匿名类的searchSku01()方法,通过new指令,创建了匿名类shopService$1的对象,并通过invokespecial调用了对象的init()。

而使用了lambda表达式的searchSku02()方法,则是通过invokedynamic指令,调用了lambda表达式。invokedynamic指令是JDK1.7引入的指令,用来支持动态语言在JVM中的执行。后面我根据大家的反馈,看看是否需要深入讲解这个指令。

那么lambda表达式的底层到底是什么呢?

实际上,lambda表达式,确实是语法糖,但不是匿名类的语法糖,而是方法(它所在的类的)的语法糖,也就是说,lambda表达式,会被编译器先转义为,它所在的外部类的一个方法,根据lambda表达式的类型不同,可能是静态方法,也可能实例方法,编译器称这个操作为“脱糖”(desugar)操作,就好像小宝宝吃棒棒糖之前,需要剥掉糖衣一样。

方法怎么变多了

从下图,idea的字节码插件jclasslib中,可以看到,在shopService类中,虽然我们只定义了四个方法,但是它的字节码文件中,却多出了三个方法,这三个方法,就是编译器对我们的

三个Lambda表达式“脱糖”之后产生的,两个静态方法,一个实例方法。

无状态(stateless)lambda表达式脱糖策略

以searchSku02()方法为例,这个表达式,没有访问外部类的任何局部变量或者属性,它是一个无状态的lambda表达式。它在脱糖之后,生成的就是静态方法,而且不需要传递额外的参数。

脱糖后字节码

从下图,可以看到,这个方法是私有静态方法(private static),synthetic关键字表示这个方法,不是源代码中原生的方法(或者说程序员自己编写的方法),而是后期合成的,是编译器添加进去的。

伪代码

下面是searchSku02()方法,脱糖之后对应的伪代码,这个不是我瞎猜的哦,是参考了openJDK官方技术文档中提供的资料。因为searchSku02()是stateless的,所以生成的方法lambda$1是静态的。

https://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html

有状态(访问局部变量)lambda表达式脱糖策略

以searchSku03()方法为例,它访问了所在方法的局部变量miniStock,但是它并没有访问外部类的属性。它在脱糖之后,生成的也是是静态方法,但是方法的参数个数发生了变化。

脱糖后字节码

伪代码

注意,在这个生成的方法中lambda$1(int miniStock,SKU sku),局部变量miniStock需要作为方法参数,传入方法中。如果lambda表达式访问了多个局部变量,就需要相应的添加多个入参。

有状态(访问外部类属性)lambda表达式脱糖策略

以searchSku04()方法为例,它访问了外部类的属性miniSales。它在脱糖之后,生成的方法,就不能是static方法了,而是实例方法。

脱糖后字节码

伪代码

注意,因为它访问了外部类的miniSales属性,生成的方法是实例方法,但是不用增加入参个数。

this关键字的本质区别

通过上面对匿名类和lambda表达式字节码文件的分析,相信大家对二者中this关键字的区别,就了然于胸了。

运行结果

总结

lambda表达式是语法糖;

但它不是匿名类的语法糖,而是方法的语法糖。

匿名类中的this,是匿名类自身。

lambda表达式中的this,是它所在的外部类。

下期预告

那么对于lambda表达式与匿名类,双方的性能如何,我们在实际项目中该如何抉择呢,下期,我翻译解读一份由Oracle公司JDK开发人员,分享的一篇有关lambda表达式与匿名类的性能评比PPT文档,帮大家解答这个问题。

参考资料

https://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html

《Java8 in Action》

后期合成 ORACLE THIS PREDICATE CLASS TEST Java 了然于胸 IDEA 详细讲解 HTTPS 众所周知 也就是说 下期预告

猜您喜欢
  • lambda表达式的“脱糖”策略 速看料
    lambda表达式的“脱糖”策略 速看料
    lambda表达式,语法比匿名类简单,可以替代匿名类,那么,lambda表达式到底是不是匿名类的语法糖;或者... 2023-01-17
  • 皮衣怎么上油保养_皮衣上色油哪里买
    皮衣怎么上油保养_皮衣上色油哪里买
    1、皮衣怎么上油:不能用皮鞋油擦拭皮衣。2、如果擦鞋油,会使鞋油内的汽油渗透到皮革内,蜡粘在皮革的... 2023-01-17
  • 羊腰子做法推荐_羊腰子的做法 最正宗的做法
    羊腰子做法推荐_羊腰子的做法 最正宗的做法
    1、羊肾杜仲汤材料:羊肾500克辅料:杜仲20克,枸杞子20克调料:葱、姜、蒜、食盐羊腰子切半,去膜、切... 2023-01-17
  • 卷头发适合什么发型_烫什么卷发好看
    卷头发适合什么发型_烫什么卷发好看
    1、中分卷发、齐肩短发、丸子发型。2、中分卷发很自然的修饰脸型,略感成熟的自然微卷长发,对于气质温... 2023-01-17
  • 【全球聚看点】瘦脸面膜推荐_瘦脸面膜推荐用语
    【全球聚看点】瘦脸面膜推荐_瘦脸面膜推荐用语
    1、马鞭草消肿面膜材料:干燥菩提花1茶匙、绿豆粉3茶匙、水100ML(20茶匙)做法:将马鞭草及菩提花浸于水中(约100 2023-01-17
  • 天天视讯!椰子水的功效作用及食用方法_椰子水的功效作用
    天天视讯!椰子水的功效作用及食用方法_椰子水的功效作用
    1 助于新陈代谢椰子水能刺激胰岛素形成,便於增强代谢速率,助于更快速的燃烧体内的糖分。2 助於减重椰子... 2023-01-17
  • 稚优泉口红什么颜色适合黄皮_稚优泉口红黄皮推荐
    稚优泉口红什么颜色适合黄皮_稚优泉口红黄皮推荐
    1、相信大家都知道口红色分为不同颜色和不同肤色人群选择的。2、稚优泉口红也是如此,稚优泉口红适合黄... 2023-01-17
  • 尿布疹和湿疹的区别图片_尿疹和湿疹的图片区别-独家焦点
    尿布疹和湿疹的区别图片_尿疹和湿疹的图片区别-独家焦点
    1、湿疹,症状可以发生在全身,比如头部,背部等等。2、婴儿湿疹是种常见的过敏性皮肤炎症,多见于牛奶... 2023-01-17
  • 过敏性鼻炎能不能吃蜂蜜_过敏性鼻炎可以吃蜂蜜吗-世界今日讯
    过敏性鼻炎能不能吃蜂蜜_过敏性鼻炎可以吃蜂蜜吗-世界今日讯
    1、过敏性鼻炎蜂蜜是可以吃的,建议适当的应用蜂蜜,含有很多微量元素,维生素等,具有很高的营养价值。2... 2023-01-17
  • 环球快讯:耐克气垫鞋真假最简单的辨别_耐克2017新款气垫鞋真假
    环球快讯:耐克气垫鞋真假最简单的辨别_耐克2017新款气垫鞋真假
    1 上世纪七十年代末,革命性的NikeAir-Sole气垫开始在Nike的鞋类产品中崭露头角。2 1987年,NikeA 2023-01-17
  • 天天看点:桑叶枕头的危害_桑叶可以做枕头有什么好处?
    天天看点:桑叶枕头的危害_桑叶可以做枕头有什么好处?
    1、桑叶枕头可以长期使用,桑叶无任何毒副作用,且制成枕头后,经过严格消毒处理,使桑叶枕头具有较高的... 2023-01-17
  • 天天快资讯:金鸡胶囊一般吃多久需要停药_金鸡胶囊一般吃多久
    天天快资讯:金鸡胶囊一般吃多久需要停药_金鸡胶囊一般吃多久
    1、发生子宫内膜炎之后,整个宫腔常常发生水肿、渗出,急性期还会导致全身症状,出现发热、寒战、白细胞... 2023-01-17
  • 世界热推荐:mac腮红多少钱_mac腮红专柜价格多少
    世界热推荐:mac腮红多少钱_mac腮红专柜价格多少
    1、2PowderBlush时尚腮红(定价$22)这个系列继承了MAC腮红贯的品质,粉质细腻,全系均是不带闪的丝缎般光滑 2023-01-17
  • 世界观天下!蔓越莓益生菌粉的功效与作用_蔓越莓益生菌有什么功效
    世界观天下!蔓越莓益生菌粉的功效与作用_蔓越莓益生菌有什么功效
    1、蔓越莓益生菌粉的主要成分是各种复合益生菌,同时也有添加定量的麦芽糊精、赤藓糖醇,当然其中少不了... 2023-01-17
  • 贝印和无印良品睫毛夹哪个好用_贝印和无印良品睫毛夹_环球微资讯
    贝印和无印良品睫毛夹哪个好用_贝印和无印良品睫毛夹_环球微资讯
    1、贝印睫毛夹这个比较特殊,前面款都是金属夹子,这个是塑料的昂~为毛和金属的混起说?因为角度确实很出... 2023-01-17
  • 口红开封后保质期一般多久_口红的保质期是几年
    口红开封后保质期一般多久_口红的保质期是几年
    1、口红的保质期通常为3年,但有些盒装口红,则因为接触空气面积大,保质期会更短。2、般来说在产品包装... 2023-01-17
  • 杰瑞米痛骂哈利王子老婆 《克拉克森的农场》或无后续
    杰瑞米痛骂哈利王子老婆 《克拉克森的农场》或无后续
    最近,热门节目《TOPGEAR》的著名主持人之一的杰瑞米·克拉克森在英国报纸《太阳报》上发表了一篇针对哈... 2023-01-17
  • 1%超级富豪拿走全球三分之二新财富:穷人越来越多 专家称应财富重分配|全球快看
    1%超级富豪拿走全球三分之二新财富:穷人越来越多 专家称应财富重分配|全球快看
    穷人越来越多,全球都是这个情况,财富分配不均匀问题越来越突出。全球新增财富正在向最富裕的阶层流动... 2023-01-17
  • 《狂飙》孟珏结局
    《狂飙》孟珏结局
    《狂飙》是一部扫黑除恶的电视剧,讲述了在京海市长达20年的黑恶势力发展史,剧中的孟珏是孟德海的女儿... 2023-01-17
  • 先用染眉膏还是先用眉笔_染眉膏怎么用 今日快看
    先用染眉膏还是先用眉笔_染眉膏怎么用 今日快看
    1、化眉所需要的化妆品主要有眉笔、眉粉、染眉膏,但是现在染眉膏的使用并没有过去那么频繁,主要适用于... 2023-01-17
  • Copyright © 2008-2015 当代娱乐网版权所有   Inc. All Rights Reserved.    联系邮箱:55 16 53 8 @qq.com  京ICP备2021034106号-22