2010-01-07 44 views
5

有人可以告訴我爲什麼會出現編譯錯誤?我不明白爲什麼在第二個for循環中對A進行強制轉換會導致strings()返回一個通用對象列表。抽象類上的參數化方法的奇怪行爲

import java.util.ArrayList; 
import java.util.List; 

public class E { 

    public static void main(String[] args) { 
     for (String s : new D().strings()) { 
      System.out.println("s = " + s); 
     } 
     for (String s : ((A) new D()).strings()) { 
      System.out.println("s = " + s); 
     } 
    } 

    static class D extends A<C> { 
    } 

    static abstract class A<T extends B> { 
     List<String> strings() { 
      return new ArrayList<String>() {{ 
       add("Foo"); 
       add("Bar!"); 
      }}; 
     } 
    } 

    static class B { 
    } 

    static class C extends B { 
    } 
} 

這是一個泛型的怪癖嗎?

謝謝你,克里斯蒂安

回答

7

在行:

for (String s : ((A) new D()).strings()) { 

您鑄造原始類型A,讓你失去了存在的類型參數信息。在Java中,原始類型的任何使用方法或字段也會導致原始類型(即使所有參數化信息都可用) - 良好的原始類型或技術上的非參數化。因此A.string()被視爲原始類型List而不是List<String>

作爲JSL指定Section 4.8:生的

的類型構造函數(§8.8),實例方法(§8.8,第9.4節),或者非靜態字段(§8.3)M類型C不是從它的超類或超接口繼承的,它是在對應於C的泛型聲明中刪除它的類型。原始類型C的靜態成員的類型與其在對應於C的泛型聲明中的類型相同。

+3

這真的很有趣。這就解釋了爲什麼如果你投給A 而不是A,它就可以工作。在這種情況下,你仍然在使用一個類型化的類。 – Shaun 2010-01-07 14:05:27

+0

+1感謝您的這個偉大的答案。我刪除了自己的答案,這不如這個。 – KLE 2010-01-07 14:06:30

+0

@Shaun,你好。部分原因是爲了避免使用原始類型而煩惱你的問題! – notnoop 2010-01-07 14:09:47