Lambda捕获与非捕获

时间:2019-01-29 20:47:55

标签: java lambda java-8 method-reference

能否请您解释为什么第一个lambda被捕获而第二个lambda没有捕获

   Runnable createLambdaWithCapture() {
      return System.out::println;
   }    
   Runnable createLambdaWithApparentCapture() {
        return () -> System.out.println();
   }

2 个答案:

答案 0 :(得分:5)

第一个代码段被捕获,因为它的计算结果System.outreturn语句被执行,且捕获相应的对象引用其Runnable#run执行内使用

在第二代码段产生Runnable未被捕获,因为System.out是只有一次该实例的run被调用的方法评价实例。自执行return语句以来,它可能已经更改。

答案 1 :(得分:2)

在第一种方法中,System.out在返回语句中立即求值。

等效的lambda就像是将System.out分解为一个变量,然后该变量成为有效的最终闭包:

Runnable createLambdaWithCapture() {
    PrintWriter foo = System.out;
    return () -> foo.println(); // foo is captured and effectively final
}

在第二种方法中,System.out(这是一个静态字段)不是最终的,可以稍后在运行时进行更改。在调用Runnable::run之前,不会调用它。

System.out = aPrintStream;
Runnable runnable1 = createLambdaWithCapture();
Runnable runnable2 = createLambdaWithApparentCapture();
System.out = anotherPrintStream;
runnable1.run(); // prints to aPrintStream
runnable2.run(); // prints to anotherPrintStream