I just performed a quick experiment in Eclipse.
public class StackTractTest {
static class Nasty {
public Integer toInt() {
if (1 == 1) throw new RuntimeException();
return 1;
}
}
@Test
public void methodReference() {
Stream.of(new Nasty())
.map(Nasty::toInt)
.findFirst();
}
@Test
public void lambda() {
Stream.of(new Nasty())
.map(n -> n.toInt())
.findFirst();
}
}
When the method-reference test fails, the trace begins
java.lang.RuntimeException
at com.example.StackTractTest$Nasty.toInt(StackTractTest.java:11)
at com.example.StackTractTest$$Lambda$1/1681433494.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
There is no reference back to the line on which the method reference is used although the end of the trace (not shown) does link back to line with findFirst
on.
While the lamdba stacktrace begins
java.lang.RuntimeException
at com.example.StackTractTest$Nasty.toInt(StackTractTest.java:11)
at com.example.StackTractTest.lambda$0(StackTractTest.java:26)
at com.example.StackTractTest$$Lambda$1/1681433494.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
Which correctly identifies the lambda was used on line 26.
Is this a peculiarity of the Eclipse compiler or is this a general disadvantage of using method references that should be considered when choosing between them and a lambda?
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.
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.
With Kotlin's sequence, using lambda and method reference have roughly the same performance. However, with Java 8 streams, using lambda is much faster than method reference. One would tend to think that using method reference should be faster than lambda because there is no additional closure.
Java provides a new feature called method reference in Java 8. 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.
No, this is how it is currently implemented.
Quoting a paper written by Brian Goetz about the translation of lambda expressions:
When the compiler encounters a lambda expression, it first lowers (desugars) the lambda body into a method whose argument list and return type match that of the lambda expression
...
Method references are treated the same way as lambda expressions, except that most method references do not need to be desugared into a new method; we can simply load a constant method handle for the referenced method and pass that to the metafactory.
The only difference between your two stacktraces is that the one with the explicit lambda has this line added:
at com.example.StackTractTest.lambda$0(StackTractTest.java:26)
It is because the lambda was translated by javac
into a newly generated method, and you can actually see in the stacktrace that this new method was lambda$0
.
With a method-reference, it is not necessary to generate a new method because it directly references an existing method.
No - in fact you get more clarity.
The fact that the at com.example.StackTractTest.lambda$0(StackTractTest.java:26)
line appears in the lambda version is reminding you that a lambda is created for this technique while using a method reference does not create anything extra.
The lambda is created at run-time, the method-reference can be constructed at compile time.
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