Why does the equivalent lambda expression and method reference behave differently when capturing the value of a static field?

I am a bit confused about the behavior of Java lambdas and methods. For example, we have this code:

import java.util.function.Consumer; public class Main { private static StringBuilder sBuilder = new StringBuilder("1"); public static void main(String[] args) { Consumer<String> consumer = s -> sBuilder.append(s); sBuilder = new StringBuilder("2"); consumer.accept("3"); System.out.println(sBuilder); } } 

Output:

 23 

This works as expected, but if we replace

s β†’ sBuilder.append (s)

from

sBuilder :: Append

the output will be:

 2 

Do you have any idea how to explain this? Is this not the same thing? Thanks.

+8
java lambda java-8 method-reference
source share
1 answer

In the lambda expression, the sBuilder field sBuilder captured, but not evaluated. It will be evaluated only when the corresponding function interface method is called. At this point, sBuilder refers to the new instance created and assigned to the field using

 sBuilder = new StringBuilder("2"); 

In the method reference, the sBuilder field is evaluated immediately to create an instance of Consumer . This value refers to the instance created in the static initializer.

 private static StringBuilder sBuilder = new StringBuilder("1"); 

and Consumer will work on it. You are printing a new one.


From the Java Language Specification Related to Estimating Runtime of a Method

The body of the invocation method depends on the form of the reference expression method, as follows:

If the form is ExpressionName :: [TypeArguments] Identifier or Primary :: [TypeArguments] Identifier , then the body of the invocation method has the effect of a method invocation expression to declare compilation time, which is a compilation time declaration of a method reference expression. The evaluation of the execution time of the call expression method is indicated in clause 15.12.4.3, clause 15.12.4.4 and Β§15.12.4.5, where:

  • The call mode is derived from the compilation time declaration, as specified in 15.12.3.

  • The target reference is an ExpressionName or Primary value, as defined when the reference method expression is evaluated.

  • Arguments for expressing a method call are formal parameters of the method call.

+10
source share

All Articles