快速看清lambda的本质

406 阅读2分钟

在JDK8之后,Lambda表达式的功能为日常开发提供了很多便捷的操作,但是没接触过的人会对这种表达式有很大的疑惑,为什么要这样表示?我要怎么写出Lambda风格的代码?本文旨在快速理解lambda。

先看下lambda表达式是什么。在JDK8中,我们可以对接口添加一个注解@FunctionalInterface,我们看下JDK中Runnalble接口

@FunctionalInterface
public interface Runnable {
    
    void run();
    
}

接口内有一个抽象方法run(),要注意一点,如果我们自己要实现一个lambda接口,那么接口内有且仅有一个抽象方法(default修饰的不算),为什么要这么限制?看完后文就知道了。

Runnable常常一起出现的是Thread类,看下Thread中是如何使用Runnable

public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

构造方法中可以传入一个Runnable对象,在JDK8之前可以使用匿名类的方式

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        // 编写运行逻辑
    }
});

这就相当于传入了一个Runnalble实例对象了。

现在思考一下,我们知道接口的参数对象是Runnable,知到Runnable仅有一个抽象方法(上文提到的限制),那我们可以简化这个表达式吗?

尝试去掉多余的参数声明语句

image.png 接着去掉多余的方法声明语句

image.png

是的,最后剩下的就是实际有效的部分,方法的参数和方法的逻辑。

最后我们加个箭头

image.png

没错,这个就是lambda表达式了,就是这么变化过来的。

考虑有参数的情况,加入Runnable接口的run方法是有参数的,例如

@FunctionalInterface
public interface Runnable {
    
    void run(String key,int val);
    
}

那么对应,lambda表达式就变成

new Thread(("hello",20) -> {
    String k = key; // k == "hello"
    int v = val;    // v == 20
});

如果方法的代码只有一行,我们可以省略中括号

new Thread(("hello",20) -> log.info("key = {}",key));