每日學習:2011.3.4 Java泛型

1、在泛型代碼內部,無法獲取任何有關泛型參數類型的信息,Java泛型是使用擦除來實現的,這意味着當你在使用泛型時,任何具體的類型信息都被擦除了。
所以需要爲泛型指定邊界(extends)=》泛型類型參數將擦除到它的第一個邊界,當具有多重邊界時,擴展基類只能有一個,而且必須放在第一位,接口可以有多個,用&來連接。

2、擦除的核心動機是它使得泛化的客戶端可以用非泛化的類庫來使用(遷移兼容性),泛型的目標是將類型安全檢查移入編譯期,避免運行時類型轉化帶來的不安全

3、擦除的補償:引入類型標籤,使用動態的isInstance()來判斷類型,通過Class<T>.newInstance()來恢復

4、創建泛型數組的唯一方式是創建一個被擦除類型的新數組,然後對其轉型=>(T[])new Object[size]
因爲有了擦除,數組的運行時類型就只能是Object[]
數組對象在底層有詳細實現,保證可以保留有關它們包含的對象類型的規則,而泛型不可以(數組支持協變)

5、關於容器的泛型:在這裏其實我們討論的是容器的類型,而不是容器持有的類型。與數組不同,泛型沒有內建的協變類型,因爲數組在語言中是完全定義的,因此可以內建編譯期和運行時的檢查。但在用泛型時編譯器和運行時系統都不知道你想用類型做些什麼,以及應該採用什麼樣的規則。

6、通配符(?):

List<? extends Fruit> fList = new ArrayList<Apple>();
//compile error:can't add any type of object
//fList.add(new Apple());
//fList.add(new Fruit());
//fList.add(new Object());
Fruit f = fList.get(0); //ok

上述代碼解釋: (? extends Fruit) 告訴編譯器類型爲一切擴展自Fruit的類型,知道這一邊界後,Fruit返回類型的get是ok的,但List的add()的參數也是(? extends Fruit),這意味着可以是任何事物,而編譯器無法驗證"任何事物"的類型安全性。

List<? extends Fruit> 你可以將其讀作“具有任何從Fruit繼承的類型的列表”,但是實際上並不意味着這個List將持有任何類型的Fruit。通配符引用的是具體類型,因此它意味着“沒有指定具體類型的List”;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章