2012-07-09 31 views
2

我注意到原始類型的通用類的可以採取(指向)的一般類的所有不同的變化,並且也是通用類的所有不同的變化可以採取(指向)的原始類型的通用類的。爲什麼Java泛型的行爲如此?純粹是因爲與舊版Java的兼容性?原始類型的泛型類可以採用該泛型類的所有不同變體的事實是Java兼容性的問題嗎?

實施例:

//Main.java 
public class Main { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 

    List listRaw = new ArrayList(); 
    List<Student> listQualified = new ArrayList<Student>(); 
    List<?> listUnbounded = new ArrayList<Student>(); 
    List<? extends Student> listUpBounded = new ArrayList<Student>(); 
    List<? super Student> listDownBounded = new ArrayList<Student>(); 

    // List raw type can take all different variations of List 
    List rawList1 = listRaw; 
    List rawList2 = listQualified; 
    List rawList3 = listUnbounded; 
    List rawList4 = listUpBounded; 
    List rawList5 = listDownBounded; 

    // All different variations of List can take List raw type 
    listRaw = rawList1; 
    listQualified = rawList2; 
    listUnbounded = rawList3; 
    listUpBounded = rawList4; 
    listDownBounded = rawList5; 

    } 

} 

//People.java 
public class People { 

    public static class Student extends People { 
    } 

    public class HistoryStudent extends Student { 
    } 

    public class MathStudent extends Student { 
    } 
} 

回答

4

Sun工程師面臨的主要挑戰之一是保持向後兼容性。 例如,如果你不能夠分配:

List list = new ArrayList<Student>(); 

那麼,你就不能使用舊庫的方法。 即:

List org.apache.commons.collections.ListUtils.intersection(List arg0, List arg1) 

還記得那些類型上運行dissapear作爲http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

+0

謝謝Ale,所以主要是出於兼容性原因。 – 2012-07-10 12:15:17

1

是。實際上泛型是在java 5中添加的,並且語言必須保持與舊版本的運行時兼容性。這種折中方法是有效的,因爲一旦代碼被編譯(鍵入ereasure)到.class中,實際上泛型信息就會消失,即使你可以通過infoby反射來獲取泛型類型參數。 如果您編譯類似於你寫它工作正常,但通常編譯器將您正在使用的「原始」類型的警告你的代碼。

+0

描述,但是這並不能解釋爲什麼你可以參數化和原材料類型之間 – newacct 2012-07-10 02:46:43

+0

因爲所有的參數類型是分配給原始類型分配。正如他所說,這是由於類型擦除主要是爲了向後兼容。編譯器會警告您這一點,您可以告訴它關閉@SuppressWarnings(「rawtypes」)註釋。 – Matt 2012-07-10 03:26:57