能否请您解释为什么第一个lambda被捕获而第二个lambda没有捕获
Runnable createLambdaWithCapture() {
return System.out::println;
}
Runnable createLambdaWithApparentCapture() {
return () -> System.out.println();
}
答案 0 :(得分:5)
第一个代码段被捕获,因为它的计算结果System.out
当return
语句被执行,且捕获相应的对象引用其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