generic-泛型/類屬
管中窺虎
在學(xué)習(xí) java 1.5 的過程中,我使用了 sun 公布的 tutorial ,這份文檔寫的比較詳盡易明,但是對(duì)于想快速了解 tiger 而且具有較好 java 基礎(chǔ)的人來說,大篇幅的英文文檔是比較耗時(shí)間和非必需的,所以我將會(huì)歸納這份文檔的主要內(nèi)容,在保證理解的底線上,盡力減少閱讀者需要的時(shí)間。
在以下地址可以進(jìn)入各新增語言特色介紹以及下載相關(guān)文檔(若有)。
http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html
第一道虎紋: generic -泛型 / 類屬
什么是泛型
泛型讓你在類這一層次上進(jìn)行抽象。看看例子:






?
?
第 3 句的轉(zhuǎn)換類型有點(diǎn)麻煩吧~?編譯器只能保證容器類里放的是 Object 對(duì)象,要使用他們只能這樣去轉(zhuǎn)換。而且這樣的轉(zhuǎn)換也并不是完全安全的,程序員可能犯錯(cuò)誤,容器里的對(duì)象未必是他以為的對(duì)象。有沒有辦法顯式地表達(dá)出程序員的意圖,將該容器限制為只能保存特定類型的對(duì)象?這正是 generic -泛型的核心用意。
?






?
這樣子我們就聲明了一個(gè)只放 Integer 的 List ,我們說 List 是一個(gè) generic Interface ,接收了一個(gè)類型參數(shù),在上例中就是 Integer 。在初始化的時(shí)候,同樣的也指定了這個(gè)類型參數(shù)。
要注意這些工作的效果不是僅僅把原來的第 3 句的轉(zhuǎn)換工作省掉,而是由此讓編譯器確保了這個(gè) List 在程序的任何位置任何時(shí)候都用以存放正確的類型,而原來的類型轉(zhuǎn)換僅僅告訴我們?cè)谶@一單點(diǎn)處程序員自己認(rèn)為的類型。
泛型由此為程序,尤其是大型程序,帶來了可讀性和健壯性。
定義簡(jiǎn)單的泛型


















尖括號(hào)內(nèi)的標(biāo)識(shí)符就是一個(gè)類型形式參數(shù)。類似于方法的參數(shù),當(dāng)你使用的時(shí)候就替換一個(gè)實(shí)際參數(shù)進(jìn)去,只不過這個(gè)參數(shù)是個(gè)類型。在上面的例子中,我們就替換了一個(gè)
Integer 類型進(jìn)去。在這里稍微說一下命名的規(guī)范,定義泛型中的形式參數(shù)時(shí),使用簡(jiǎn)潔有力又具有啟發(fā)性的名字,如果可以的話用單個(gè)字母更好。避免使用小寫,以免和普通的方法參數(shù)混淆。
泛型與子類
看看以下的例子語句合法嗎?
?




?
第 2 句是行不通的,看看以下的語句:




簡(jiǎn)而言之就是,原有類型的繼承關(guān)系是不會(huì)反映到對(duì)應(yīng)的泛型上來,在上述情況下,任何兩個(gè)泛型類型都不存在繼承關(guān)系。那么,習(xí)慣了面向接口編程的我們?cè)鯓尤ミm應(yīng)這種嚴(yán)格的使用限制呢?
通配符
假如我們要用一個(gè)方法把一個(gè)容器內(nèi)的元素都 print 出來,可以用這樣的代碼來實(shí)現(xiàn) :













?????} ?

如果我們用新的泛型和新的
for 語句(你可以先不了解它,以后會(huì)談到)來嘗試同樣的功能,以下代碼可行嗎?













?
事實(shí)是,新的代碼的使用范圍非常有限,因?yàn)?/span>
Collection
<
Object
>
就只是一個(gè)放
Object
的容器泛類,它不是
任何其他
Collection
泛類的父類!真正擔(dān)任這個(gè)角色的是:
Collection
<
?
>
這個(gè)問號(hào)代表了未知,
Collection
<
?
>
的元素可以是任何類型,這就是通配類型。
現(xiàn)在我們可以這樣寫:











? } ?

?
注意在循環(huán)里面,可以把元素賦值給一個(gè) Object 類型,因?yàn)闊o論 c 里放的是什么,它肯定是一個(gè) Object ,但向 c 里放置對(duì)象則是不安全的,因?yàn)椴恢?/span> c 的泛型是什么。如下面這樣是不行的:




?
add() 方面接納的是泛型的形式參數(shù)里描述的類型(或它的子類,希望你對(duì)此不感到混亂,呵呵。),然而此時(shí)我們只看到一個(gè)問號(hào),我們不知道它的類型參數(shù)是什么,當(dāng)然就不能放置對(duì)象進(jìn)去。唯一一個(gè)例外是 null ,它是任何一個(gè)類型的對(duì)象集的一分子。
受限通配符
省去一些說明性的代碼,以我們熟悉的幾何圖形家族例子來說明:
?
一個(gè) List<T> ,如果 T 是 Shape 的子類,那么這個(gè) List 都可以被上面這個(gè)方法接納為參數(shù),這個(gè)就是受限的通配符。 Shape 就稱為這個(gè)通配符的上限。
看看下面的代碼,怎樣?








如上的方法依然是不行的,因?yàn)槲覀冎恢?/p>
shapes 是 Shape 或者其子類型的容器,然而具體類型是什么不知道,它未必是 Rectangle 的父類,所以不能放置元素進(jìn)去。
總結(jié)起來,我們要了解的事情有:
l???????? 泛型的用意
l???????? 泛型的幾種形式(普通,通配符,受限通配符)
l???????? 泛型與繼承關(guān)系一起使用時(shí)的易錯(cuò)傾向,尤其是向泛型容器添加元素的情況。
posted on 2006-08-22 11:11 Binary 閱讀(547) 評(píng)論(1) 編輯 收藏 所屬分類: j2se