1. 概述
泛型在java中有很重要的地位,在面向?qū)ο缶幊碳案鞣N設(shè)計(jì)模式中有非常廣泛的應(yīng)用。
什么是泛型?為什么要使用泛型?
泛型,即“參數(shù)化類型”。一提到參數(shù),最熟悉的就是定義方法時(shí)有形參,然后調(diào)用此方法時(shí)傳遞實(shí)參。那么參數(shù)化類型怎么理解呢?顧名思義,就是將類型由原來(lái)的具體的類型參數(shù)化,類似于方法中的變量參數(shù),此時(shí)類型也定義成參數(shù)形式(可以稱之為類型形參),然后在使用/調(diào)用時(shí)傳入具體的類型(類型實(shí)參)。
泛型的本質(zhì)是為了參數(shù)化類型(在不創(chuàng)建新的類型的情況下,通過(guò)泛型指定的不同類型來(lái)控制形參具體限制的類型)。也就是說(shuō)在泛型使用過(guò)程中,操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù),這種參數(shù)類型可以用在類、接口和方法中,分別被稱為泛型類、泛型接口、泛型方法。
為什么要使用泛型?我們來(lái)看一個(gè)例子:


上面程序在編譯時(shí)沒(méi)有任何問(wèn)題,但是當(dāng)運(yùn)行時(shí)肯定會(huì)報(bào)錯(cuò),如下圖所示:
由于ArrayList中可以存放任意類型,所以上面例子中add String和Integer類型不會(huì)有任何問(wèn)題,但是在使用時(shí)把a(bǔ)rrayList中的數(shù)據(jù)全當(dāng)作String類型來(lái)用,肯定會(huì)有問(wèn)題。為了解決這個(gè)問(wèn)題,使程序正常運(yùn)行我們需要進(jìn)行類型判斷。如下面所示:

這樣程序可以正常運(yùn)行了,但是可以看出這樣用起來(lái)比較麻煩,因?yàn)槲覀兙椭皇窍朐赼rrayList中存放String類型,但是由于各種原因arrayList中可能被添加非String類型,在操作arrayList中的數(shù)據(jù)時(shí),我們一是需要我們進(jìn)行類型判斷,二是需要進(jìn)行強(qiáng)制類型轉(zhuǎn)換。

那有沒(méi)有辦法只允許arrayList中只能添加String類型,添加其他類型在編譯時(shí)就直接報(bào)錯(cuò),然后使用arrayList中的元素時(shí),直接當(dāng)成String類型使用,而不需要進(jìn)行類型判斷以及強(qiáng)制類型轉(zhuǎn)換呢?這時(shí)泛型就應(yīng)運(yùn)而生了。我們用泛型改造一下上面的例子:

使用泛型后,如果添加非String類型數(shù)據(jù)時(shí),編譯時(shí)直接會(huì)報(bào)錯(cuò),如果用eclipse、intellij idea等IDE開發(fā)工具編寫程序的話,添加非String類型數(shù)據(jù)時(shí)直接會(huì)提示錯(cuò)誤,如下:
2.泛型的使用
泛型有三種使用方式,分別為:泛型類、泛型接口、泛型方法。
泛型類
泛型類型用于類的定義中,被稱為泛型類。通過(guò)泛型可以完成對(duì)一組類的操作對(duì)外開放相同的接口。最典型的就是各種容器類,如:ArrayList、HashSet、HashMap。

泛型類的定義如下:
下面是一個(gè)常見的泛型類使用方法:


那么問(wèn)題來(lái)了,定義的泛型類,在實(shí)例化對(duì)象時(shí)就一定要傳入泛型類型實(shí)參么?并不是這樣,在使用泛型的時(shí)候如果傳入泛型實(shí)參,則會(huì)根據(jù)傳入的泛型實(shí)參做相應(yīng)的限制,此時(shí)泛型才會(huì)起到本應(yīng)起到的限制作用。如果不傳入泛型類型實(shí)參的話,在泛型類中使用泛型的方法或成員變量定義的類型可以為任何的類型。比如List、Map等集合類型。

看下面的例子:
注意:
? ? ? 1:泛型的類型參數(shù)只能是類類型,不能是普通的基本類型。
? ? ? 2:不能對(duì)確切的泛型類型使用instanceof操作,如下面的操作是非法的,編譯時(shí)就會(huì)報(bào)錯(cuò):

泛型接口
泛型接口與泛型類的定義及使用基本相同。泛型接口常被用在各種類的生產(chǎn)器中,可以看一個(gè)例子: