2015-11-13 22 views
8

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

} 

、トレースは

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) 

を開始し、バックトレースの端部(図示せず)がメソッド参照が使用されている行への参照はありませんオンラインでfindFirstとリンクしています。

lamdbaのスタックトレースが正しくラムダを識別

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) 

はライン26

で使用されていたから始まりますが、これはEclipseのコンパイラのクセですかこれはメソッドの参照を使用しての一般的な欠点でありますそれらとラムダの間で選択するときに考慮する必要がありますか?

+2

いいえ、これはJavaの仕組みです。彼らはスタックトレースの経験を改善するために働いています –

+1

私は決して前にもっと長いスタックトレースを求める開発者を聞いたことがありません... – Holger

答えて

4

いいえ、これは現在実装されています。その引数リストと戻り値の型が一致するメソッドに

コンパイラはラムダ式に遭遇すると、最初に低下する(desugars)ラムダ本体:ラムダ式の翻訳についてのブライアン・ゲッツによって書かれたa paperを引用

メソッドの参照は、ほとんどのメソッドの参照が新しい方法に脱糖する必要がないことを除いて、ラムダ式と同じように扱われ

...ラムダ式のこと。参照メソッドの定数メソッドハンドルをロードしてメタファクトに渡すだけで済みます。

あなたの2つのスタックトレース間の唯一の違いは、明示的なラムダとの1は、この行を追加したことである。

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

をラムダが新しく生成された方法にjavacによって翻訳されたので、それがあり、そしてあなたこの新しいメソッドがlambda$0であったことをスタックトレースで実際に見ることができます。

メソッド参照では、既存のメソッドを直接参照するため、新しいメソッドを生成する必要はありません。

2

いいえ - 実際にはもっと明確になります。

at com.example.StackTractTest.lambda$0(StackTractTest.java:26)ラインは、ラムダバージョンに表示されているという事実は、メソッドのリファレンスを使用すると、余分なものを作成しませんが、ラムダは、この技術のためを作成されたことを思い出させています。

ラムダは実行時に作成され、メソッド参照はコンパイル時に作成できます。

+2

ありがとうございます。スタックトレースは何が起きているかを正確に表していますが、ラムダバージョンでは、エラーが発生した時点を特定するという実用的な利点があります。この情報は、メソッド参照には使用できないように見えます。メソッド参照がパイプラインで複数回出現した場合、どのインスタンスが実行時例外をトリガしたのかが分かると便利です。 – henry

+2

しかし、それはエラーが発生した時点ではありません。生成時間は、ラムダまたはメソッドハンドルの使用時間と同じではありません。ラムダをスレッドプールに送信するとします。このエラーは、ラムダを発行するメソッドが既に終了しているときに、ずっと後に発生します。基本的にはコールサイトの代わりにアロケーションサイトを求めています。伝統的には含まれていない情報スタックトレースです。それは、「スレッドプールに提出された実行可能ファイルがどこに割り当てられているか」と尋ねるようなものです。 – the8472

関連する問題