| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 聊一下JDK8中,Lambda表达式实现原理 -> 正文阅读 |
|
[移动开发]聊一下JDK8中,Lambda表达式实现原理 |
概念Lambda表达式,也称函数编程,百度百科概念: Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。 从上面的概念上看,Lambda表达式其实就是一个没有名字的函数。但有一个问题,Java并没有函数的这个概念,那JDK8之后所说的函数是啥意思呢? 答案:Java中函数就是函数接口中抽象方法的实现逻辑 再具体点:函数接口抽象方法的方法体 表现形式:
以线程Runable接口为例子
JDK8之前,普通匿名内部类实现
JDK8之后,Lambda实现
Thread类传入的对象就是lambda表达式对象:()-> {System.out.println("....");},这也就概念上讲的Java函数。 如果你认真观察,你就会发现Thread接收参数是Runable接口的run方法实现。 案例分析需求:定义一个函数接口,使用常规方式、匿名内部类方式与lambda方式实现 定义一个函数接口:
方式1:常规的实现方式
方式2:匿名内部类实现方式
方式3:使用Lambda实现方式
2种方式实现的效果一样,使用lambda方式实现更加简洁方便。同时也有点无厘头,特别是没有学习或完全掌握Lambda语法的同学,说不出的奇怪感。那Lambda究竟是啥回事? 原理要弄懂这个lambda表达式实现原理,需要借助JDK自带的Java class文件分解器:javap 工具 步骤1:检查java的环境变量 注意:必须配置了JAVA环境变量 ?步骤2:查看字节码基本信息 进入到项目字节码(.class)文件所在目录,演示案例使用的maven结构项目,所以进入target目录。
?观察返回的字节码信息,有个特殊的方法
看到这,可以大胆做推断:当类中使用lambda 表达式,编译器会自动创建一个私有的,静态的,格式为: lambda$方法名$序号?方法。 步骤3:验证?lambda$方法名$序号方法?推断 这里我们可以确认推断是否正确, 在InterfaceDemo? 类上加上相同方法签名的方法
然后执行run操作 编译没问题,但一执行马上抛异常,异常明显指定跟新增的方法有关。 到这,证明上面推断是对的。 步骤4:大胆猜测,小心求证 上面推断是正确的, 那我们不禁要问,lambda$main$0?方法是干什么的,跟lambda表达式有啥关系?回想下,刚刚案例分析中提到实现方式:? 常规方式:定义一个新类:MyInterfaceImpl?实现接口MyInterface 匿名内部类方式:定义一个匿名的类,实现接口MyInterface 上面2种都需要一个接口实现类,Lambda表达式能实现相同功能,那是否可以推断lambda表达式的实现方式也必须要有一个接口实现类呢??完全可以取验证一下: Lamdba 表达方式: 在执行InterfaceDemo 类main方法之前, 先配置VM?options,目的:JVM运行时将动态创建类字节码对象打印处理。
?运行之后得到结果 ?用idea打开:
?惊讶发现,lambda语法确实创建了一个MyInterface接口实现类,名字为:InterfaceDemo$$Lambda$14,那么
可以认为等价于
?步骤5:真相大白 到这,离真相大白就剩下一步之遥了: 最后一个问题,InterfaceDemo$$Lambda$14()类中sayHi方法是怎么重写的?
内部类InterfaceDemo$$Lambda$14重写接口方法sayHi直接调用:InterfaceDemo的lambda$main$0(); 方法 而lambda$main$0 方法是编译器自动生成的。那lambda$main$0 方法的方法体是啥,实现了啥逻辑? 再次使用javap命令查看字节码对象与编译流程(此次查看更详细的编译过程)
这种命令查看信息更全,截取重要的信息
上面的代码是类似汇编语言,从旁边的注释上能看出lambda$main$0方法大概实现了。 lambda$main$0 方法在方法体重,调用了PrintStream类的println方法,打印的值是字符:hello lambda...? ?也即: System.out.println("hello lambda...."); 哇塞~ 真相大白了。 步骤6:总结 我们从头梳理一下: lambda表达式写法
编译之后的写法:
总结 Lambda表达式实现原理: 1>JDK编译时会给使用lambda表达式的类中添加一个私有的,静态的方法, 格式:lambda$方法名$序号? 2>JDK编译时动态创建一个局部内部类,该类实现了函数接口,重写函数接口唯一的抽象方法。 3>局部内部类重写接口抽象方法:直接调用步骤1中新增的私有的,静态的方法。 最后的最后,用大白话讲请求lambda表达式原理: Lambda表达式就一个语法糖,本质还是常规的接口实现,只是将实现过程做了简化。 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 1:32:50- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |