2017-02-26 61 views
8

Başka bir yanıt oluştururken, investigating a stack trace discrepancy iken, anlamadığım bir davranışla karşılaştım.Yığın izlemede gizemli satır

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

} 

Hatları 11 ve 13 yukarıdaki snippet'te etiketli ve run on ideone olabilir: (bu kadarıyla aşağı bunu daralabilir gibidir) Aşağıdaki test programı düşünün. o programın çıktısı:

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) 

Benim soru şudur: Neden, ikinci ve üçüncü test durumları için yığın izleme hattı 11 mı? Üç test vakası arasındaki fark, bildirilen tipler a ve b'dur.

Hat 11 (sınıf bildirimi hattı), aşağıdaki koşullar altında, sadece mevcut olduğu: Test bir arabirim uygulayan

  1. ise ve
  2. durum arabirim yöntemi atılır ise, ve
  3. sınıf bildirgede tür parametresi extends Test<T> içeriyorsa arayüzü bir tür parametresi ve
  4. alırsa (hat 11 o class Test<T> olarak bildirilirse dahil değildir) ve
  5. Yöntem, Test türünden ziyade TestInterface türünde çağrılırsa. belirten

:

Kesinlikle benim istisnası atılır
  • (mesaj ve yığın izleme).
  • Benimkini atmazsam başka hiçbir özel durum atılmaz.
  • Bunu, Oracle JDK 1.7 ve Windows'ta 1.8 ve Ideo'da 1.8 ile yeniden ürettim. Ancak, 1.7, 11 yerine (1 kat garip olan) 1. satırda bir yığın izi öğesi içerir.

Burada neler oluyor? Bu satır yığın izinde nasıl biter ve her iki nesne de Test olarak bildirilmişse neden görünmez? aComparable olarak ilan ancak Enum olarak ilan edildiği mevcut değilse java.lang.Enum hattı 55 mevcut olduğunu

Here is the original program that prompted this

. Satır 55, JDK kaynağındaki Enum bildirgesidir, satır 180, açıkça atılmış ClassCastException'dur.

cevap

13

bridge method'un etkilerine bakıyorsunuz! TestInterface bildirilen

test yöntem silinmesini test(Object), ama Test bildirilen test yöntem silinmesini test(Test) sahiptir. test(Object) yöntemine yönelik bir yöntem arayışı, test(Test) yöntemini bulamayacağından, Java, Test'ın bayt koduna ayrı ayrı test(Object) ve test(Test) yöntemlerini koyar.

İlk deneme beklendiği gibi davranır test(Test) yöntemini kullanır. Sizin diğer çalışmalar sadece test(Test) yöntemini çağıran bir sentetik köprü yöntemidir test(Object) yöntemi kullanır. Bu köprü yöntem gerçekten bir satır sayısı bilgisi yoktur, bu nedenle bu 11.

oldukça rasgele hat numarası ile yığın izleme gösterir