一、什么是泛型擦除
- 偽泛型
假如我們定義一個容器類(蘋果籃類)用來存放蘋果,則可以按照以下簡單實現(xiàn):
那么如果現(xiàn)在又需要定一個容器類(香蕉籃類)用來存放香蕉,那么可以按以下簡單實現(xiàn):class Fruit{} class Apple extends Fruit{} class BucketApple{ private Apple apple; public Apple getApple() {return apple;} public void setApple(Apple apple) {this.apple = apple;} }
可以發(fā)現(xiàn)的是,類class Fruit{} class Banana extends Fruit{} class BucketBanana{ private Banana banana; public Banana getBanana() {return banana;} public void setBanana(Bananabanana) {this.banana = banana;} }BucketBanana和BucketApple有著相似之處,根據(jù)多態(tài)的原理我們可以直接使用Object類替代所有水果類(相當(dāng)于用Object做了Apple類和Banana類的泛型),那么蘋果籃和香蕉籃就可以簡化為一個水果籃:
實際中,Java本身也是利用Object實現(xiàn)的偽泛型,比如在代碼中定義class Bucket{ private Object obj; public Object getObject() {return obj;} public void setObject(Object obj) {this.obj = obj;} }List<String>和List<String>等類型,在編譯后都會變成List,List底層存放的都是Object類型的對象,而不是定義時附加的類型信息String、Integer。// ArrayList底層源碼,通過Object數(shù)組存放對象 transient Object[] elementData; - 泛型擦除
還是用上面的List為例,實際存放的都是Object對象,定義List<Integer>時聲明的Integer只是用來檢查存入對象的類型。流程如下圖所示:
-
無界通配符擦除
-
有界通配符擦除
-
擦除方法中類型定義的參數(shù)
-
擦除接口中的泛型標(biāo)識
二、泛型擦除相關(guān)問題和注意事項
- 先檢查還是先編譯?類型校驗的根據(jù)是什么?引用傳遞問題
-
Q: 由上述可知編譯時會進(jìn)行泛型擦除,數(shù)據(jù)均轉(zhuǎn)換為Object存儲,那么定義集合如下,為什么在add(整數(shù))時還是提示錯誤?
A: Java編譯器是通過先檢查代碼中泛型的類型,然后再進(jìn)行類型擦除,再進(jìn)行編譯。public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("123"); list.add(123); //編譯錯誤 } -
Q: 根據(jù)什么進(jìn)行類型檢查?引用中的限制類型還是初始化中的限制類型?
A: 初始化時的new ArrayList()只是在內(nèi)存開辟了一個存儲空間,可存儲任意類型對象。泛型是根據(jù)引用對象中聲明的限制類型進(jìn)行校驗。public class Test { public static void main(String[] args) { ArrayList<String> list1 = new ArrayList(); list1.add("1"); //編譯通過 list1.add(1); //編譯錯誤 String str1 = list1.get(0); //返回類型就是String ArrayList list2 = new ArrayList<String>(); list2.add("1"); //編譯通過 list2.add(1); //編譯通過 Object object = list2.get(0); //返回類型就是Object new ArrayList<String>().add("11"); //編譯通過 new ArrayList<String>().add(22); //編譯錯誤 String str2 = new ArrayList<String>().get(0); //返回類型就是String } }
- 自動類型轉(zhuǎn)換
- 類型擦除與多態(tài)的沖突和解決方法
- 泛型類型變量不能是基本數(shù)據(jù)類型
- 編譯時集合的instanceof
- 泛型在靜態(tài)方法和靜態(tài)類中的問題
詳情參見鏈接



