前言:
??當(dāng)元素存入集合時(shí)袭蝗,集合會(huì)將元素轉(zhuǎn)換為Object類型存儲(chǔ)唤殴,當(dāng)取出時(shí)也是按照Object取出的,所以用get方法取出時(shí)到腥,我們會(huì)進(jìn)行強(qiáng)制類型轉(zhuǎn)換朵逝,并且通過代碼也可以看出來,我們放入其他類型時(shí)乡范,如字符串配名,編譯器不會(huì)報(bào)錯(cuò),但是運(yùn)行程序時(shí)會(huì)拋出類型錯(cuò)誤異常晋辆,這樣給開發(fā)帶來很多不方便渠脉,用泛型就解決了這個(gè)麻煩。
??泛型規(guī)定了某個(gè)集合只能存放特定類型的屬性瓶佳,當(dāng)添加類型與規(guī)定不一致時(shí)芋膘,編譯器會(huì)直接報(bào)錯(cuò),可以清楚的看到錯(cuò)誤霸饲。
??當(dāng)我們從List中取出元素時(shí)直接取出即可为朋,不用類型轉(zhuǎn)換,因?yàn)橐呀?jīng)規(guī)定了里面存放的只能是某種類型厚脉。
??集合中中除了存入定義的泛型類型的實(shí)例习寸,還可以存入泛型類型子類的實(shí)例。
??泛型不能是基本類型傻工,只能是引用類型霞溪,如果必須使用基本類型孵滞,可以使用基本類型的包裝類。
一.泛型是什么鸯匹?
?Java 泛型是 JDK 5 中引入的一個(gè)新特性, 泛型提供了編譯時(shí)類型安全檢測(cè)機(jī)制坊饶,該機(jī)制允許程序員在編譯時(shí)檢測(cè)到非法的類型。
泛型的本質(zhì)是參數(shù)化類型忽你,也就是說所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)幼东。
通俗的講,泛型就是操作類型的 占位符科雳,即:假設(shè)占位符為T根蟹,那么此次聲明的數(shù)據(jù)結(jié)構(gòu)操作的數(shù)據(jù)類型為T類型。
二.泛型方法
- 所有泛型方法聲明都有一個(gè)類型參數(shù)聲明部分(由尖括號(hào)分隔)糟秘,該類型參數(shù)聲明部分在方法返回類型之前(在下面例子中的<E>)简逮。
- 每一個(gè)類型參數(shù)聲明部分包含一個(gè)或多個(gè)類型參數(shù),參數(shù)間用逗號(hào)隔開尿赚。一個(gè)泛型參數(shù)散庶,也被稱為一個(gè)類型變量,是用于指定一個(gè)泛型類型名稱的標(biāo)識(shí)符凌净。
- 類型參數(shù)能被用來聲明返回值類型悲龟,并且能作為泛型方法得到的實(shí)際參數(shù)類型的占位符。
- 泛型方法體的聲明和其他方法一樣冰寻。注意類型參數(shù)只能代表引用型類型须教,不能是原始類型(像int,double,char的等)。
下面給出使用不同類型數(shù)組打印元素的實(shí)例
public class GenericMethodTest {
public static <E> void printArray(E[] arrays) {
for(E e : arrays) {
System.out.print(e+" ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] intArray = {10,20,33,14,53};
Double[] doubleArray = {53.1,25.6,56.8,22.1,25.3};
String[] stringArray = {"Apple","Banana","Watermelon","Strawberry"};
System.out.println("整型數(shù)組元素為:");
printArray(intArray);
System.out.println("雙精度浮點(diǎn)數(shù)數(shù)組元素為:");
printArray(doubleArray);
System.out.println("字符串?dāng)?shù)組元素為:");
printArray(stringArray);
}
}
運(yùn)行結(jié)果如下:
整型數(shù)組元素為:
10 20 33 14 53
雙精度浮點(diǎn)數(shù)數(shù)組元素為:
53.1 25.6 56.8 22.1 25.3
字符串?dāng)?shù)組元素為:
Apple Banana Watermelon Strawberry
有界參數(shù)類型:
一個(gè)操作數(shù)字的方法可能只希望接收Number以及Number的子類實(shí)例斩芭。為了限制傳遞類型參數(shù)的范圍轻腺,我們可以聲明一個(gè)有界的類型參數(shù),如何列出類型參數(shù)的名稱划乖,后接extends和他的上界贬养。
下面我們使用一個(gè)例子來說明:
public static <T extends Comparable<T>> T maxnum(T x,T y,T z) {
T max= x;
if(y.compareTo(max)>0) {
max = y;
}
if(z.compareTo(max)>0) {
max = z;
}
return max;
}
public static void main(String[] args) {
System.out.println("85, 55, 54中最大的數(shù)字為:"+maxnum(85, 55, 54));
System.out.println("apple watermelon orange中最大的字符為:" + maxnum("apple", "watermelon", "orange"));
}
二.泛型類
??泛型類的類型參數(shù)聲明部分也包含一個(gè)或多個(gè)類型參數(shù),參數(shù)間用逗號(hào)隔開琴庵。一個(gè)泛型參數(shù)误算,也被稱為一個(gè)類型變量,是用于指定一個(gè)泛型類型名稱的標(biāo)識(shí)符细卧。因?yàn)樗麄兘邮芤粋€(gè)或多個(gè)參數(shù)尉桩,這些類被稱為參數(shù)化的類或參數(shù)化的類型。
接下來我們演示一個(gè)實(shí)例:
public class Box<T>{
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
Box<Integer> integBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integBox.add(88);
stringBox.add("Hello World!");
System.out.println("整形值為:" + integBox.get());
System.out.println("字符串為:" + stringBox.get());
}
}
運(yùn)行結(jié)果:
整形值為:88
字符串為:Hello World!
三.類型通配符
類型通配符一般是使用?代替具體的類型參數(shù)贪庙。例如 List<?> 在邏輯上是List<String>,List<Integer> 等所有List<具體類型實(shí)參>的父類。
public class GenericTest {
public static String getData(List<?> data) {
return "data:" + data.get(0);
}
public static void main(String[] args) {
List<String> course = new ArrayList<String>();
List<Integer> no = new ArrayList<Integer>();
List<Number> num = new ArrayList<Number>();
course.add("CS");
no.add(19);
num.add(30);
System.out.println(getData(course));
System.out.println(getData(no));
System.out.println(getData(num));
}
}
運(yùn)行結(jié)果:
data:CS
data:19
data:30
四.Java泛型實(shí)現(xiàn)原理:類型擦除
??Java的泛型是偽泛型翰苫。在編譯期間止邮,所有的泛型信息都會(huì)被擦除掉这橙。正確理解泛型概念的首要前提是理解類型擦出(type erasure)。
??Java中的泛型基本上都是在編譯器這個(gè)層次來實(shí)現(xiàn)的导披。在生成的Java字節(jié)碼中是不包含泛型中的類型信息的屈扎。使用泛型的時(shí)候加上的類型參數(shù),會(huì)在編譯器在編譯的時(shí)候去掉撩匕。這個(gè)過程就稱為類型擦除鹰晨。
?? 如在代碼中定義的List<object>和List<String>等類型,在編譯后都會(huì)變成List止毕。JVM看到的只是List模蜡,而由泛型附加的類型信息對(duì)JVM來說是不可見的。Java編譯器會(huì)在編譯時(shí)盡可能的發(fā)現(xiàn)可能出錯(cuò)的地方扁凛,但是仍然無法避免在運(yùn)行時(shí)刻出現(xiàn)類型轉(zhuǎn)換異常的情況忍疾。