1.测试类 public class LamdaTest { Runnable r1 = () -> { System.out.println(this); }; public static void main(String[] args) { new LamdaTest().r1.run(); } @Override public String toString() { return "hahaha"; } } |
2.配置启动参数-Djdk.internal.lambda.dumpProxyClasses,运行 |
3.反编译生成的两个类 javap -c -p LamdaTest.class (图一) javap -c -p LamdaTest$$Lambda$1.class (图二) |
【Java8: lamda表达式实现原理分析】4.分析 LamdaTest的实例对象记为:L LamdaTest$$Lambda$1实例对象记为:R 反编译LamdaTest$$Lambda$1类 final class LamdaTest$$Lambda$1 implements Runnable { private final LamdaTest arg$1; private LamdaTest$$Lambda$1(LamdaTest var1) { this.arg$1 = var1; } private static Runnable get$Lambda(LamdaTest var0) { return new LamdaTest$$Lambda$1(var0); } @Hidden public void run() { this.arg$1.lambda$new$0(); } } |
LamdaTest构造函数字节码分析: public com.ljw.LamdaTest(); Code: 0: aload_0#L加载进操作数栈 1: invokespecial #1 // Method java/lang/Object." 4: aload_0#L加载进操作数栈 5: aload_0#L加载进操作数栈 此时栈顶两个L 6: invokedynamic #2, 0 //InvokeDynamic#0:run(Lcom/ljw/LamdaTest; )Ljava/lang/Runnable; #最终调用 LamdaTest$$Lambda$1的get$Lambda静态方法 ,其中会执行【return new LamdaTest$$Lambda$1( L ); 】这句,返回R对象,放入栈顶。 11: putfield #3// Field r1:Ljava/lang/Runnable; #此时栈内元素为 L,R , 执行本条语句 L.r1 = R 14: return |
1.在 LamdaTest 的 main 方法中调用【new LamdaTest().r1.run();
】 2.接着执行LamdaTest$$Lambda$1.run方法中的【 this.arg$1.lambda$new$0(); 】 arg$1表示第1步中构造的LamdaTest类型的对象L。 3.接着会调用 LamdaTest 的实例方法 lambda$new$0,查看LamdaTest的反编译文件,此方法的内容就是【 () -> {System.out.println(this); } 】这个lamda表达式中的内容。 |
5.总结 1.在LamdaTest 类中生成一个私有方法,包装lamda表达式方法体 2.LamdaTest$$Lambda$1 中间类,起到代理的作用,最终调用 LamdaTest 中生成的私有方法。这个中间类实现函数式接口,含有一个LamdaTest的属性,含有一个返回 LamdaTest$$Lambda$1 实例的方法。 |
图一

文章图片
图二

文章图片
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)