緣由
之前l(fā)eetcode刷題的時候,某道題試圖新建一個HashMap
的數(shù)組,總是編譯出錯捕传,然后突然反應(yīng)過來,Java里是不能按照像通常新建基本類型的數(shù)組一樣债鸡,直接新建泛型數(shù)組的江滨。希望我能以比較簡單明了的方式說明其中的原因。
分析
首先對于Java數(shù)組厌均,數(shù)組必須明確知道內(nèi)部元素的類型唬滑,而且編譯器會”記住“這個類型,每次往數(shù)組里插入新元素都會進行類型檢查莫秆,不匹配會拋出java.lang.ArrayStoreException
錯誤间雀。
如果試圖創(chuàng)建一個泛型數(shù)組,直接寫成下面這樣的話:
HashMap<Integer> map = new HashMap<Integer>[];
其實是無法編譯通過的镊屎。
原因就是Java的泛型是通過類型擦除(type erasure)來實現(xiàn)的惹挟。什么是類型擦除呢,簡單來說Java在編譯期間缝驳,所有的泛型信息都會被擦除掉连锯。
如在代碼中定義的List<object>
和List<String>
等類型,在編譯后都會變成List
用狱。
List<String> strList = new ArrayList<String>();
List<Object> objList = new ArrayList<Object>();
List rawList = new ArrayList();
比如上面3個List运怖,擦除類型參數(shù)以后,List中的實際元素都是Object夏伊。JVM看到的只是List摇展,而由泛型附加的類型信息對JVM來說是不可見的。
Java編譯器會在編譯時盡可能的發(fā)現(xiàn)可能出錯的地方溺忧,但是仍然無法避免在運行時刻出現(xiàn)類型轉(zhuǎn)換異常的情況咏连。所以由于類型擦除的原因,Java是禁止直接創(chuàng)建泛型數(shù)組實例的鲁森。
泛型數(shù)組
如何創(chuàng)建真正的泛型數(shù)組呢祟滴?我們不能直接創(chuàng)建,但可以把數(shù)組強制轉(zhuǎn)換成泛型類型歌溉。比如:
List<Integer>[] genericArray = (List<Integer>[])new ArrayList[10];
這樣編譯的時候并不會報錯垄懂,因為Java雖然禁止直接創(chuàng)建泛型數(shù)組實例,但并沒有禁止聲明一個泛型數(shù)組引用痛垛。所以仍然可以通過強制轉(zhuǎn)型原生類型數(shù)組的方式草慧,繞過限制。
雖然編譯期不會報錯榜晦,但是這樣做仍然有潛在的風(fēng)險冠蒋,因為類型擦除的存在,遇到下面這種情況運行期間就掛了:
List<Integer>[] genericArray = (List<Integer>[])new ArrayList[10];
genericArray[0] = new ArrayList<String>(Arrays.asList(new String[]{"Hello"}));
總結(jié)
Java 中不允許直接創(chuàng)建泛型數(shù)組乾胶,所以并不建議通過各種方式繞過編譯器的限制抖剿,這樣會帶來在代碼出錯時朽寞,編譯器也有可能無法及時發(fā)現(xiàn)錯誤,從而帶來潛在的風(fēng)險斩郎。
想要用泛型數(shù)組的時候脑融,還是老老實實用ArrayList
吧!缩宜。
參考文章:
[[1]]java為什么不支持泛型數(shù)組肘迎? - 胖胖的回答 - 知乎
[[2]]Java 泛型總結(jié)(二):泛型與數(shù)組