In the first method, System.out
is evaluated immediately in the return statement.
The equivalent lambda would be as if you factored System.out
out to a variable which then becomes an effectively final closure:
Runnable createLambdaWithCapture() {
PrintWriter foo = System.out;
return () -> foo.println(); // foo is captured and effectively final
}
In the second method, System.out (which is a static field) is not final and could be changed later at runtime. It is not invoked until Runnable::run
is invoked.
System.out = aPrintStream;
Runnable runnable1 = createLambdaWithCapture();
Runnable runnable2 = createLambdaWithApparentCapture();
System.out = anotherPrintStream;
runnable1.run(); // prints to aPrintStream
runnable2.run(); // prints to anotherPrintStream