Are stack traces less accessible when using method references against lambdas?

I just did a quick experiment at 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 help method 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 to the line where the method reference is used, although the end of the trace (not shown) refers to the line with findFirst on.

While stackdrace lamdba 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) 

What correctly identifies the lambda was used in line 26.

Is this a feature of the Eclipse compiler or is it a common disadvantage of using method references that should be considered when choosing between them and the lambda?

+8
java stack-trace lambda java-8 method-reference
source share
2 answers

No, that's how it is currently implemented.

Quote an article written by Brian Goetz about translating lambda expressions:

When the compiler encounters a lambda expression, it first drops (desugars) the lambda body into a method whose argument list and return type match the lambda expression

...

Method references are handled in the same way as lambda expressions, except that most method references do not need to be dropped into the new method; we can just load the constant method descriptor for the reference method and pass it to the metafile.

The only difference between your two stacks is that this line is added in one explicit iambed:

 at com.example.StackTractTest.lambda$0(StackTractTest.java:26) 

This is because lambda has been transferred by javac to the newly generated method, and you can really see on the stack that this new method was lambda$0 .

Using a method reference, there is no need to generate a new method, since it directly refers to an existing method.

+4
source share

No - you are actually getting more clarity.

The fact that the string at com.example.StackTractTest.lambda$0(StackTractTest.java:26) appears in the lambda version reminds you that lambda is created for this method, while using the method reference does not create anything superfluous.

A lambda is created at runtime, a method reference can be built at compile time.

+2
source share

All Articles