泛型:聲明中具有一個(gè)或多個(gè)類型參數(shù)的類或者接口就是泛型
原生態(tài)類型的泛型:不帶任何實(shí)際參數(shù)的泛型名稱,例如List<E>的原生態(tài)類型就是List
使用原生態(tài)類型的安全性問(wèn)題
如果我們?cè)诼暶鞣盒偷臅r(shí)候使用了原生態(tài)類型的泛型啦桌,但是最后添加數(shù)據(jù)的時(shí)候卻添加了與初始化數(shù)據(jù)不同的類型的數(shù)據(jù)锨匆,例如這種
List nameList = new ArrayList();
nameList.add(1);
//然后添加
nameList.add("java");
這種錯(cuò)誤在編譯時(shí)并沒(méi)有什么問(wèn)題宰僧,但是運(yùn)行時(shí)會(huì)報(bào)錯(cuò)乐严。如上所述坛芽,如果不提供類型參數(shù),使用集合類型和其他泛型也任然是合法的七嫌,但是不應(yīng)該這么做。如果使用原生類型苞慢,就失掉了泛型在安全性和表述性方面的所有優(yōu)勢(shì)诵原。
泛型的子類化
如上所述,雖然不應(yīng)該在新代碼中使用想List這樣原生態(tài)類型,使用參數(shù)化的類型以允許插入任意對(duì)象绍赛,如List<Object> ,這還是可以的蔓纠。原生態(tài)類型List和參數(shù)化類型List<Object>之間到底有什么區(qū)別呢?
不嚴(yán)格的說(shuō)吗蚌,前者逃避了泛型的檢查腿倚,后者明確告訴編譯器,它能夠持有任意類型的對(duì)象褪测。雖然你可以將List<String>傳遞給類型List的參數(shù)猴誊,但是不能將它傳給類型List<Object>的參數(shù)。
無(wú)限制的通配符類型
有了泛型之后呢會(huì)有一種比較安全的替代方法侮措,稱作無(wú)限制的通配符類型(Unbounded wildcard type)懈叹。
如果要使用泛型,但不確定或者不關(guān)心實(shí)際的類型參數(shù)分扎,就可以使用一個(gè)問(wèn)號(hào)替代澄成。例如,泛型Set<E> 的無(wú)限制通配符類型為 Set<?>(讀作“某個(gè)類型的集合”)畏吓。這是最普通的參數(shù)化Set集合墨状,可以持有任何集合
無(wú)限制通配符類型Set<?> 和原生態(tài)類型Set的區(qū)別
這個(gè)問(wèn)號(hào)真正起到作用了嗎?這個(gè)是當(dāng)然起到作用的菲饼,因?yàn)橥ㄅ浞愋蜁r(shí)安全的肾砂,原生態(tài)類型不安全。由于可以將任何元素放進(jìn)原生態(tài)類型的集合中宏悦,因此很容易破壞改集合的類型約束條件镐确;
總之,使用原生態(tài)類型會(huì)在運(yùn)行時(shí)導(dǎo)致異常饼煞,因此不要再新代碼中使用源葫。但就有人問(wèn)既然這么不推薦使用,為什么還要存在原生態(tài)類型呢砖瞧?原生態(tài)類型只是為了與引入泛型之前的遺留代碼進(jìn)行兼容和互換而提供的息堂。讓我們做個(gè)快速的回顧:Set<Object> 是個(gè)參數(shù)化類型,所以可以包含任何對(duì)象類型的一個(gè)集合块促;Set<?> 則是一個(gè)通配符類型荣堰,表示只能包含某種位置對(duì)象類型的一個(gè)集合;Set則是原生態(tài)類型竭翠,它脫離了泛型系統(tǒng)持隧。前兩個(gè)是安全的,最后一種不安全逃片。