首页 > 技术文章 > Lambda表达式运行原理

ason-wxs 2020-07-27 15:55 原文

JDK8引入了Lambda表达式以后,对我们写代码提供了很大的便利,那么Lambda表达式是如何运用简单表示来达到运行效果的呢?今天,我们通过一个例子来学习下Lambda表达式的底层运行原理!

一、创建测试样例

首先:我们创建一个测试类App.java,在它内部新建一个函数式接口Lam.java,只有一个抽象方法print(),作用是将传入的消息加工后再输出。

然后:我们在测试类App.java中进行lambda表达式的创建测试。

代码如下:

public class App {
    public static void main(String[] args) {
        Lam lam = (msg) -> "log:" + msg;
        String result = lam.print("Test");
        System.out.println(result);
    }
}

interface Lam {
    String print(String msg);
}

二、利用Java命令编译分析

首先,我们进行javac命令的编译,会生成两个class文件:

javac App.java
编译后文件

然后,我们通过javap -p命令打开Lam.class:

javap -p Lam.class
Lam.class

从图中我们可以看到,因为Lam.class是App.class的内部类,所以提示我们它是App.java编译过来的,并且其内部只有一个abstract方法print()。

接下来,我们再打开App.class:

javap -p App.class
App.class

App.class中一共有三个方法,一个默认构造方法,一个main方法,还多了一个我们没有定义过的方法:lambda$main$0(String),很明显,这个方法就是lambda表达式内逻辑操作方法,它是一个static的方法,入参就是我们传入的msg类型String。

那么,这个lambda$main$0(String)方法是怎么被调用的呢?我们通过对java命令指定选项查看底层详细的编译过程:

java -Djdk.internal.lambda.dumpProxyClasses App
App

我们能够看到多出来一个App$$Lambda$1.class文件,打开文件:

javap -p App$$Lambda$1.class
App

我们看到,这个类是一个实现Lam接口的final类,它内部实现了print()方法。

我们再通过javap -c查看一下它内部详细信息:

javap -c App$$Lambda$1.class
详细信息

由此我们可以看出,App$$Lambda\(1.class的print()方法执行了App.lambda\)main$0(),因此,我们就可以得出结论:

  1. Java在编译时,首先,在App内将Lambda表达式抽取出来作为一个static方法lambda$main$0(String)
  2. 然后,对Lam.class做了默认实现App$$Lambda$1.class,并在内部print()方法中调用了App内的static方法:lambda$main$0()
  3. 接下来,执行App的main()方法时,就会对lambda表达式利用实现类的print()方法运行;
  4. 最后,将结果返回,并打印。

这就是Lambda表达式的底层运行逻辑。

三、文末

以上,就是我们通过一个实例,运用Java命令,来理解Lambda表达式的底层运行原理的全部内容,希望对你有所帮助!

O(∩_∩)O

推荐阅读