Lambda

Lambda 表达式描述了一个代码块(或者叫匿名方法),可以将其作为参数传递给构造方法或者普通方法以便后续执行。考虑下面这段代码:

() -> System.out.println("沉默王二")
  • () 为 Lambda 表达式的参数列表(本例中没有参数)

  • -> 标识这串代码为 Lambda 表达式(也就是说,看到 -> 就知道这是 Lambda)

  • System.out.println("沉默王二") 为要执行的代码,即将“沉默王二”打印到标准输出流

例子:Runnable

原来我们创建一个线程并启动它是这样的:

public class LamadaTest {
    public static void main(String[] args) {
        new (new Runnable() {
            @Override
            public void run() {
                System.out.println("沉默王二");
            }
        }).start();
    }
}

通过 Lambda 表达式呢?只需要下面这样:

为什么可以这么写?Runnable在源码中,通过 @FunctionalInterface 标记的接口可以通过 Lambda 表达式创建实例:

更多实例

  • 为变量赋值

  • 作为 return 结果

  • 作为数组元素

  • 作为普通方法或者构造方法的参数

作用域范围

下面这段代码在编译的时候会提示错误:从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量

和匿名内部类一样,不要在 Lambda 表达式主体内对方法内的局部变量进行修改,否则编译也不会通过:Lambda 表达式中要用到的,但又未在 Lambda 表达式中声明的变量,必须声明为 final 或者是 effectively final,否则就会出现编译错误

关于 final 和 effectively final 的区别:

那哪些情况可以修改呢?

static 变量可以在 static 方法中的 Lambda 表达式中修改:

把 limit 变量声明为 AtomicInteger:AtomicInteger 可以确保 int 值的修改是原子性的,可以使用 set() 方法设置一个新的 int 值,get() 方法获取当前的 int 值。

使用数组的方式略带一些欺骗的性质,在声明数组的时候设置为 final,但更改 int 的值时却修改的是数组的一个元素:

Lambda 和 this 关键字

Lambda 表达式并不会引入新的作用域,这一点和匿名内部类是不同的。也就是说,Lambda 表达式主体内使用的 this 关键字和其所在的类实例相同。

最后更新于