一些術語
- 參數化類的類型(parameterized type):含有類型參數的類型,例如List<String>
- 原生態類型(raw type):沒有類型參數的類型,例如List
- 無限制通配符類型(unbounded wildcard type):例如List<?>
原生態類型保留的原因:兼容性
List, List<Object>, List<String>, List<?>的討論
- 形如List的是原生態類型,是類型不安全的,逃避了泛型檢查
- List<Object>明確告訴編譯器它可以持有Object類型的對象,List<String>明確告訴編譯器它可以持有String類型的對象,但是List類型的引用可以接受List<Object>,List<String>的實例對象,但是List<Object>的引用不可以接受List<String>的實例對象。也就是所謂的泛型集合是不具有協變性(covariant)的.
- 無限制通配符類型如List<?>說明該List持有某種特定類型的對象,但是不知道具體是哪一種類型,所以不能向這種List中添加任何對象,因爲編譯器並不能 判定這種添加是否是正確的,所以會在編譯階段報錯。相比原生態類型,List則可以添加任何對象,因爲編譯階段並沒有做類型檢查。
優先使用列表而不是數組
數組是協變的(covariant),所謂數組是協變的,是指如果Sub是Super的子類型,那麼數組類型Sub[]也是Super[]的子類型。
而泛型是通過擦除(erasure)來實現的,泛型是隻在編譯時強化它們的類型信息,並在運行時丟棄它們的元素類型信息。所以泛型不是協變的,上面第2條List<Object>並不是List<String>的父類。
所以數組和泛型不能很好的混用,如創建泛型對象數組:new E[],參數化類型或者類型參數的數組:new List<E>[], new List<String>[]是非法的。
類型擦除對泛型的限制
由於泛型僅僅是在編譯時有了較強的類型檢查,而實際編譯後所產生的是沒有泛型信息的運行代碼,所以這導致泛型有許多限制。
- 泛型類中,static方法和static域均不可引用類的類型變量
- 不能實例化泛型類型實例,也就是使用類似於new T()的形式
- 不能實例化泛型數組
Comparable<T>接口
實現Comparable<T>接口,實現其中的compareTo方法可以使對象的對比更高效。
參考文獻:使用通配符簡化泛型使用