Java8: lamda表达式实现原理分析

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 (图二)

 

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."":()V #初始化L

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 实例的方法

 

 

图一Java8: lamda表达式实现原理分析_第1张图片

 图二Java8: lamda表达式实现原理分析_第2张图片

 

 

 

你可能感兴趣的:(JAVA)