從Java5開始肋乍,泛型成為了Java語言的一部分蒲祈。在沒有泛型之前,從集合中讀取的每一個對象都必須進(jìn)行轉(zhuǎn)換台夺。
泛型的優(yōu)點(diǎn):編譯器會自動為你的插入進(jìn)行轉(zhuǎn)換,并在編譯時告知是否插入了類型錯誤的對象痴脾。這樣使程序更加安全颤介、也更加清楚。
泛型:聲明中具有一個或者多個類型參數(shù)(type parameter)的類或者接口赞赖。
- 請不要使用原生態(tài)類型
每一種泛型都定義一個原生態(tài)類型(raw type)滚朵,即不帶任何實(shí)際類型參數(shù)的泛型名稱。例如List<E>對應(yīng)的原生態(tài)類型是List前域。它們存在的主要是為了與泛型出現(xiàn)之前的代碼相兼容辕近。
如果使用原生態(tài)類型,就失掉了泛型在安全性和描述性方面的所有優(yōu)勢匿垄。
在不確定或者不在乎集合中的元素類型的情況下移宅,你也許會使用原生態(tài)類型。例如椿疗,編寫一個方法漏峰,有兩個集合,返回他們共有的元素?cái)?shù)量届榄。使用原生態(tài)類型固然可行芽狗,但這是很危險的。安全的替代做法是使用無限制的通配符類型痒蓬,例如童擎,泛型Set<E>的無限制通配符類型為Set<?>(讀作“某個類型的集合”)。這是最普通的參數(shù)化Set類型攻晒,可以持有任何集合顾复。
Set、Set<?>和Set<Object>區(qū)別:原生態(tài)類型不安全鲁捏,可以將任何元素放進(jìn)原生態(tài)類型的集合中芯砸,很容易破壞該集合的類型約束類型條件。Set<?>不能將任何元素(除了null之外)放到Set<?>中给梅。Set<Object>是個參數(shù)化類型假丧,可以包含任何對象類型的一個集合。
消除非受檢的警告
用泛型編程時會遇到許多編譯器警告:非受檢轉(zhuǎn)換警告动羽、非受檢方法調(diào)用警告包帚、非受檢參數(shù)化可變參數(shù)類型警告、非受檢轉(zhuǎn)換警告运吓。
要盡可能的消除每一個非受檢警告渴邦。如果消除了所有警告,就可以確保代碼是類型安全的拘哨。這意味著不會出現(xiàn)Class-Cast-Exception谋梭。
如果無法消除警告,同時可以證明引起警告的代碼是類型安全的倦青,(只有這種情況下)才可以使用一個@SuppressWarnings("unchecked")注解來禁止這條警告瓮床。列表優(yōu)于數(shù)組
a. 數(shù)組是協(xié)變的(covariant),例如如果Sub是Super的子類型产镐,那么數(shù)組類型Sub[]就是Super[]的子類型隘庄。而泛型是不可變的(invariant),List不會是List的基類磷账,更不會是它的子類峭沦。協(xié)變會破環(huán)泛型類型安全,因此泛型不是協(xié)變的逃糟。
b. 數(shù)組是具體化的(reified)吼鱼,而泛型在運(yùn)行時是被擦除的(erasure)。數(shù)組是在運(yùn)行時才去判斷數(shù)組元素的類型約束绰咽,而泛型正好相反菇肃,在運(yùn)行時,泛型的類型信息是會被擦除的取募,只有編譯的時候才會對類型進(jìn)行強(qiáng)化琐谤。
http://www.it610.com/article/5143909.htm
可具體化類型:就是一個可在整個運(yùn)行時可知其類型信息的類型。 包括:基本類型玩敏、非泛型類型斗忌、原始類型和調(diào)用的非受限通配符质礼。
不可具體化類型:無法整個運(yùn)行時可知其類型信息的類型,其類型信息已在編譯時被擦除织阳。例如:List<String>和List<Number>眶蕉,JVM無法在運(yùn)行時分辨這兩者
java泛型是編譯器泛型,是一種語法糖唧躲,生成的二進(jìn)制代碼中是沒有泛型的造挽,jvm感受不到泛型。java的泛型編譯生成二進(jìn)制代碼的時候弄痹,進(jìn)行了類型的擦除饭入,放入集合的實(shí)際上是object類型,從集合中獲取對象的時候 獲取的是object類型肛真, 然后進(jìn)行了強(qiáng)制類型轉(zhuǎn)換谐丢,轉(zhuǎn)換成實(shí)際的類型。
```
//java.lang.ArrayStoreException: java.lang.Integer
Object[] array = new String[10];
array[0] = 10;
//這段代碼連編譯都不能通過毁欣。
List<Object> list2 = new ArrayList<String>();
list.add(10);
```
所以上面的例子中庇谆,數(shù)組的方法會在運(yùn)行時報(bào)出ArrayStoreException壳鹤,而泛型根本無法通過編譯价捧。
為什么創(chuàng)建泛型數(shù)組是非法的?因?yàn)樗皇穷愋桶踩木υ肌T倥e個例子
```
List<String>[] stringLists = new List<String>[1];
List<Integer> intList = List.of(42);
Object[] objects = stringLists;
objects[0] = intList;
String s = stringLists[0].get(0);
```
具有不可具體化形參的可變參數(shù)方法的潛在隱患:發(fā)生堆污染
堆污染(Heap Pollution): 發(fā)生時機(jī):當(dāng)一個參數(shù)化類型變量引用了一個對象执解,而這個對象并非此變量的參數(shù)化類型時寞肖,堆污染就會發(fā)生。分模塊對代碼進(jìn)行分別編譯衰腌,那就很難檢測出潛在的堆污染新蟆,應(yīng)該同時編譯
帶泛型的可變參數(shù)問題: T...將會被翻譯為T[],根據(jù)類型擦除右蕊,進(jìn)一步會被處理為Object[]琼稻,這樣就可能造成潛在的堆污染
避免堆污染警告 :
@SafeVarargs
:當(dāng)你確定操作不會帶來堆污染時,使用此注釋關(guān)閉警告
@SuppressWarnings({"unchecked", "varargs"})
:強(qiáng)制關(guān)閉警告彈出(不建議這么做)