Can you please explain why the first lambda is capturing and the second not.
Runnable createLambdaWithCapture() {
return System.out::println;
}
Runnable createLambdaWithApparentCapture() {
return () -> System.out.println();
}
Captures default to const value. By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them.
Fewer Lines of Code − One of the most benefits of a lambda expression is to reduce the amount of code. We know that lambda expressions can be used only with a functional interface. For instance, Runnable is a functional interface, so we can easily apply lambda expressions.
You do not have to create a functional interface in order to create lambda function.
Generally speaking, lambdas and streams provide a more concise and (once everyone is up to speed) more readable way of expressing this kind of algorithm.
The first snippet is capturing because it evaluates System.out
when the return
statement is executed and captures the corresponding object reference to be used within its Runnable#run
implementation.
The second snippet generates a Runnable
instance that is not capturing because System.out
is only evaluated once that instance's run
method is invoked. It could have changed since the time the return
statement was executed.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With