Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are stack traces less navigable when using method references vs lambdas?

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?

like image 448
henry Avatar asked Nov 13 '15 11:11

henry


People also ask

Why method reference is better than 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.

Are there any differences between lambda expressions and method references?

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.

Are method references faster?

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.

What is the advantage of using method reference in Java 8?

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.


2 Answers

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.

like image 73
Tunaki Avatar answered Oct 22 '22 17:10

Tunaki


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.

like image 24
OldCurmudgeon Avatar answered Oct 22 '22 19:10

OldCurmudgeon