使用方法引用vs lambdas时,堆栈跟踪是否更少可导航?

hen*_*nry 8 java lambda stack-trace java-8 method-reference

我刚刚在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();
  }

}
Run Code Online (Sandbox Code Playgroud)

当方法引用测试失败时,跟踪开始

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)
Run Code Online (Sandbox Code Playgroud)

虽然跟踪的末尾(未显示)确实链接回到具有findFirston的行,但是没有对使用方法引用的行的引用.

而lamdba stacktrace开始了

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)
Run Code Online (Sandbox Code Playgroud)

第26行使用了正确识别lambda的方法.

这是Eclipse编译器的特性还是使用方法引用的一般缺点,在选择它们和lambda时应该考虑这些引用?

Tun*_*aki 5

不,这是当前的实现方式。

引用的论文 Brian Goetz撰写有关lambda表达式的翻译写:

当编译器遇到lambda表达式时,它首先将lambda主体降低(删除)到其参数列表和返回类型与lambda表达式的参数匹配的方法中

...

方法引用与lambda表达式的处理方式相同,不同之处在于,大多数方法引用不需要分解为新方法;我们可以简单地为引用的方法加载一个常量方法句柄,并将其传递给元工厂。

您的两个堆栈跟踪之间的唯一区别是,带有显式lambda的堆栈跟踪添加了以下行:

at com.example.StackTractTest.lambda$0(StackTractTest.java:26)
Run Code Online (Sandbox Code Playgroud)

这是因为将lambda转换javac为新生成的方法,并且您实际上可以在stacktrace中看到该新方法是lambda$0

使用方法引用时,无需生成新方法,因为它直接引用现有方法。