I have two factory-methods which produce "consumers" use different approaches 👉🏻 lambda and method references:
@SuppressWarnings("Convert2MethodRef")
public Consumer<String> lambdaPrintStringConsumer(){
return x -> System.out.println(x);
}
public Consumer<String> methodRefPrintStringConsumer(){
return System.out::println;
}
I found that in first case (lambdaPrintStringConsumer()
), method return reference to the same object
@Test
public void shouldSameFromFactoryMethod_lambda() {
Consumer<String> consumerA = lambdaPrintStringConsumer();
Consumer<String> consumerB = lambdaPrintStringConsumer();
Assert.assertSame(consumerA, consumerB);//consumerA == consumerB --> true
}
but in the second (methodRefPrintStringConsumer()
), objects is different
@Test
public void shouldNotSameFromFactoryMethod_methodRef() {
Consumer<String> consumerA = methodRefPrintStringConsumer();
Consumer<String> consumerB = methodRefPrintStringConsumer();
Assert.assertNotSame(consumerA, consumerB);//consumerA == consumerB --> false
}
direct approach return the same result as shouldNotSameFromFactoryMethod_methodRef()
:
@SuppressWarnings("Convert2MethodRef")
@Test
public void shouldNotSameFromLambda() {
Consumer<String> consumerA = s -> System.out.println(s);
Consumer<String> consumerB = s -> System.out.println(s);
Assert.assertNotSame(consumerA, consumerB);//consumerA == consumerB --> false
}
, next I tested factory-method with method reference to other static method
public class FunctionalInterfaceTest {
public static Consumer<String> methodRefFromStaticMethodStringConsumer() {
return FunctionalInterfaceTest::print;
}
public static void print(String string) {
System.out.println(string);
}
...
}
and get the same result as in the first test (lambdaPrintStringConsumer
):
@Test
public void shouldSameFromFactoryMethod_methodRef() {
Consumer<String> consumerA = methodRefFromStaticMethodStringConsumer();
Consumer<String> consumerB = methodRefFromStaticMethodStringConsumer();
Assert.assertSame(consumerA, consumerB );//consumerA == consumerB --> true
}
What is the trick❓
In Tests 👉🏻 jdk-11.0.1
and jdk-13.0.1
.
A lambda expression (lambda) is a short-form replacement for an anonymous class. Lambdas simplify the use of interfaces that declare single abstract methods. Such interfaces are known as functional interfaces. A functional interface can define as many default and static methods as it requires.
Because the lambda expression provides a body to only a single abstract method.
You can define a lambda expression that would represent an A instance regardless of the context you are in. It can be a static interface method, it could be a default interface method.
Are the following expressions equivalent?
x -> System.out.println(x)
System.out::println
No. If you call System.setOut
, the former will pick up the new PrintStream
; the latter will not.
So, in this case, the lambda method does not require access to variables from the enclosing lexical scope, whereas this method reference expression does. This allow the former to be shared but the latter cannot.
The exact details may or may not be specified - I can't be bothered to look.
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