首先,我們要從概念上認(rèn)識(shí)泛型,泛型的作用是什么?泛型是為了能夠在編譯時(shí)而不是在運(yùn)行時(shí)檢測(cè)出錯(cuò)誤而產(chǎn)生的,以提高程序的可靠性、健壯性和魯棒性。
有部分讀者可能會(huì)有這樣的理解誤區(qū):
如定義泛型ArrayList<String>list,比定義原始類型ArrayList list,能提高程序運(yùn)行的效率,能減少JVM底層識(shí)別數(shù)據(jù)類型的時(shí)間。
注意!不管實(shí)際的具體類型是什么,泛型類是被它的所有實(shí)例所共享的,在JVM中只有原始類型被存儲(chǔ)為單獨(dú)一個(gè)類
如下面的例子所示
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<Integer> list2 = new ArrayList<Integer>();
System.out.println(list1 instanceof ArrayList); //true
System.out.println(list2 instanceof ArrayList); //true
System.out.println(list1 instanceof ArrayList<String>); //false
由此可知,泛型存在于編譯時(shí),一旦編譯器確認(rèn)泛型類型是安全使用的,就會(huì)將它轉(zhuǎn)換為原始類型,JVM中只含有原始類型,所以上面的理解是錯(cuò)誤的,泛型對(duì)運(yùn)行時(shí)是毫無意義的,更談不上提高效率。
正由于泛型的這個(gè)特點(diǎn),所以不能用泛型類型參數(shù)創(chuàng)建實(shí)例:
E object = new E(); // false
此外,不能用泛型類型參數(shù)創(chuàng)建數(shù)組:
E[] elements = new E [capacity]; //false
同時(shí)不建議使用強(qiáng)制類型轉(zhuǎn)換:
E[] elements = (E[])new Object [capacity];
如果 E 是 String,而 new Object[] 是 Integer 對(duì)象的數(shù)組,那么 (String[]) (new Object[]) 將會(huì)導(dǎo)致 ClassCastException 異常。
在靜態(tài)環(huán)境下、異常類也是不能使用泛型的。
下面我們來觀察一個(gè)例子:
import java.util.ArrayList;
import java.util.List;
class A {
}
class B extends A {
}
class D extends B {
}
public class TestGenericType {
public static void main(String[] args) {
List list = new ArrayList();
List<A> listA = new ArrayList<A>();
list = listA;// A正確
List<B> listB = new ArrayList<B>();
// listA=listB;//B錯(cuò)誤
List<Object> listObject = new ArrayList<Object>();
List<?> list$ = new ArrayList<>();
list$ = listObject;// C正確
List<D> listD = new ArrayList<D>();
List<? extends B> listExtendsB = new ArrayList<>();
listExtendsB = listD;// D正確
List<? extends A> listExtendsA = new ArrayList<>();
// listA = listExtendsA;//E錯(cuò)誤
listExtendsA = listExtendsB;// F正確
List<? super B> listSuperB = new ArrayList<>();
listSuperB = listB;// G正確
// listSuperB = listExtendsB;//H錯(cuò)誤
}
}
其中, ? 、 ? extends T 、 ? super T 是通配泛型。
? --->非受限通配,它和 ? extends Object 一樣
? extends T --->受限通配,表示 T 或 T 的一個(gè)未知子類型
? super T --->下限通配,表示 T 或 T 的一個(gè)未知父類型
它們的關(guān)系如下圖(摘自《Java語言程序設(shè)計(jì)》進(jìn)階篇)
我們來做下分析:
【A】由第一張圖的例子可知,listA instanceof list
【B】盡管 B 是 A 的子類,但 List<B> 不是 List<A> 的子類,所以 listA = listB 是錯(cuò)誤的
【C】? 同等于 ? extends Object,list$ 能接收 Object 或 Object 的一個(gè)未知子類型,所以能接收 listObject
【D】解釋同“C”
【E】同“A”,若 listExtendsA 接收的是 B 類,則 List<B> 不是 List<A> 的子類
【F】listExtendsA 能接收 A 或 A 的子類,正確
【G】listSuperB 能接收 B 或 B 的父類,正確
【H】listSuperB 不能接收 B 的子類,listExtendsB 可能接收 D類