2017-02-26 22 views
8

investigating a stack trace discrepancy別の回答を作成するとき、私は理解できない振る舞いに出会った。スタックトレース中の不思議な線

interface TestInterface <U> { 
    void test (U u); 
} 

static class Test <T extends Test<T>> implements TestInterface<T> { // line 11 
    @Override public void test (T t) { 
     throw new RuntimeException("My exception"); // line 13 
    } 
} 

static class TestA extends Test<TestA> { } 
static class TestB extends Test<TestB> { } 

public static void main (String[] args) throws Exception { 

    try { 
     Test a = new TestA(); 
     Test b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

    try { 
     TestInterface a = new TestA(); 
     Test b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

    try { 
     TestInterface a = new TestA(); 
     TestInterface b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

} 

線11と13は、上記のスニペットにラベル付けされており、それがrun on ideoneにすることができます(これは限りダウン私はそれを狭めることができている)は、次のテストプログラムを考えてみましょう。そのプログラムの出力は次のようになります。

java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone.main(Main.java:25) 
java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone$Test.test(Main.java:11) 
    at Ideone.main(Main.java:33) 
java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone$Test.test(Main.java:11) 
    at Ideone.main(Main.java:41) 

私の質問は:なぜ第二と第三のテストケースのスタックトレースの行11がありますか? 3つのテストケースの違いには、abの宣言されたタイプがあります。

ライン11(クラス宣言ライン)は、以下の条件下でのみ存在している:Testインターフェイスを実装

  1. 場合、及び
  2. は例外がインターフェースメソッドからスローされた場合、及び
  3. インターフェイスが型パラメータを受け取り、
  4. の場合、クラス宣言の型パラメータにextends Test<T>class Test<T>と宣言されている場合は11行目は含まれません)と
  5. TestタイプではなくTestInterfaceタイプでメソッドが呼び出された場合。それに注目

それは間違いなく私の例外がスローされ
  • (メッセージとスタックトレース)。
  • 私が鉱山を投じなければ、他に例外はありません。
  • これは、Oracle JDK 1.7、Windowsでは1.8、Ideoneでは1.8で再現しました。しかし、1.7には11の代わりに1行目のスタックトレース要素が含まれています(これは二重に奇妙です)。

ここで何が起こっているかその行はスタックトレースでどのように終わるのですか?そして、両方のオブジェクトがTestと宣言されていると、なぜ表示されませんか? aComparableとして宣言され、それはEnumとして宣言されたときに存在しない場合java.lang.Enumのライン55が存在する

Here is the original program that prompted this、。行55はJDKソースのEnumの宣言であり、行180は明示的にClassCastExceptionをスローしたものです。

答えて

13

あなたはbridge methodの効果を見ています!

TestInterfaceで宣言さtest方法は、消去test(Object)を持っていますが、Testで宣言さtest方法は、消去test(Test)を持っています。 test(Object)メソッドのメソッドルックアップではtest(Test)メソッドが見つからないため、Javaでは実際に別のtest(Object)test(Test)メソッドをTestのバイトコードに入れます。

最初の試行では、test(Test)メソッドが使用されます。これは、期待どおりに動作します。あなたの他の試行ではtest(Object)メソッドを使用します。これはtest(Test)メソッドを呼び出す合成ブリッジメソッドです。このブリッジメソッドは実際には行番号を持たないため、かなり任意の行番号11のスタックトレースに表示されます。

関連する問題