I'm a little bit confused about Java lambdas and method references behaviour. For ex., 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)
with
sBuilder::append
the output will be:
2
Have you any ideas how to explain this? This isn't the same things? Thanks.
Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined by the functional interface while a method reference is similar to a lambda expression that refers a method without executing it.
out::println); The method references can only be used to replace a single method of the lambda expression. A code is more clear and short if one uses a lambda expression rather than using an anonymous class and one can use method reference rather than using a single function lambda expression to achieve the same.
Method reference is used to refer method of functional interface. It is compact and easy form of lambda expression. Each time when you are using lambda expression to just referring a method, you can replace your lambda expression with method reference.
In order to match a lambda to a single method interface, also called a "functional interface", several conditions need to be met: The functional interface has to have exactly one unimplemented method, and that method (naturally) has to be abstract.
In the lambda expression, the sBuilder
field is captured, but not evaluated. It will only be evaluated when the corresponding function interface method is invoked. At that point, the sBuilder
references the new instance created and assigned to the field with
sBuilder = new StringBuilder("2");
In the method reference, the sBuilder
field is evaluated immediately to produce a Consumer
instance. That value references the instance created in the static initializer
private static StringBuilder sBuilder = new StringBuilder("1");
and the Consumer
will operate on that one. You print the new one.
From the Java Language Specification, concerning the Run-Time Evaluation of Method References
The body of an invocation method depends on the form of the method reference expression, as follows:
If the form is
ExpressionName :: [TypeArguments] Identifier
orPrimary :: [TypeArguments] Identifier
, then the body of the invocation method has the effect of a method invocation expression for a compile-time declaration which is the compile-time declaration of the method reference expression. Run-time evaluation of the method invocation expression is as specified in §15.12.4.3, §15.12.4.4, and §15.12.4.5, where:
The invocation mode is derived from the compile-time declaration as specified in §15.12.3.
The target reference is the value of
ExpressionName
orPrimary
, as determined when the method reference expression was evaluated.The arguments to the method invocation expression are the formal parameters of the invocation method.
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