1、定義
泛型,即“參數(shù)化類型”。一提到參數(shù),最熟悉的就是定義方法時有形參,然后調用此方法時傳遞實參。那么參數(shù)化類型怎么理解呢?
顧名思義,就是將類型由原來的具體的類型參數(shù)化,類似于方法中的變量參數(shù),此時類型也定義成參數(shù)形式(可以稱之為類型形參),然后在使用/調用時傳入具體的類型(類型實參)。
泛型的本質是為了參數(shù)化類型(在不創(chuàng)建新的類型的情況下,通過泛型指定的不同類型來控制形參具體限制的類型)。也就是說在泛型使用過程中,操作的數(shù)據(jù)類型被指定為一個參數(shù),這種參數(shù)類型可以用在類、接口和方法中,分別被稱為泛型類、泛型接口、泛型方法。
2、栗子
舉個眾人皆知的例子:
public static void main(String[] args) {
List list = new ArrayList();
list.add("asdf");
list.add(123);
// TODO Auto-generated method stub
for (int i = 0; i < list.size(); i++) {
System.out.println("list.get[" + i + "] == " + (String)list.get(i));
}
}
編譯時不會報錯,但是一旦運行,程序就會崩潰,報錯如下:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
例子中添加了一個String類型,添加了一個Integer類型,再使用時都以String的方式使用,因此程序崩潰了。為了解決類似這樣的問題(在編譯階段就可以解決),泛型應運而生。
我們在初始化list的時候就指定類型,編譯器就能在編譯階段幫我們發(fā)現(xiàn)類似問題;
public static void main(String[] args) {
List<String> list = new ArrayList();//為list指定String類型
list.add("asdf");
list.add(123);//添加int型數(shù)據(jù)就會報錯,編譯無法通過,避免運行時崩潰
// TODO Auto-generated method stub
for (int i = 0; i < list.size(); i++) {
System.out.println("list.get[" + i + "] == " + (String)list.get(i));
}
}
3、泛型擦除
泛型只在編譯階段有效;
public static void main(String[] args) {
List<String> stringList = new ArrayList<String>();
List<Integer> integerList = new ArrayList<Integer>();
Class classStringArrayList = stringList.getClass();
Class classIntegerArrayList = integerList.getClass();
if(classStringArrayList.equals(classIntegerArrayList)){
System.out.println("泛型相同");
}
}
運行結果:泛型相同;
通過上面的例子可以證明,在編譯之后程序會采取去泛型化的措施。也就是說Java中的泛型,只在編譯階段有效。在編譯過程中,正確檢驗泛型結果后,會將泛型的相關信息擦除,并且在對象進入和離開方法的邊界處添加類型檢查和類型轉換的方法。也就是說,泛型信息不會進入到運行時階段。
對此總結成一句話:泛型類型在邏輯上看以看成是多個不同的類型,實際上都是相同的基本類型。
4、使用
泛型有三種使用方式,分別為:泛型類、泛型接口、泛型方法。