當前位置:才華齋>計算機>java語言>

初步理解Java的泛型特性分享

java語言 閱讀(6.2K)

初步理解Java的泛型特性

初步理解Java的泛型特性分享

在Java SE1.5中,增加了一個新的特性:泛型(日本語中的總稱型)。何謂泛型呢?通俗的說,就是泛泛的指定物件所操作的型別,而不像常規方式一樣使用某種固定的型別去指定。泛型的本質就是將所操作的資料型別引數化,也就是說,該資料型別被指定為一個引數。這種引數型別可以使用在類、介面以及方法定義中。

一、為什麼使用泛型呢?

在以往的J2SE中,沒有泛型的情況下,通常是使用Object型別來進行多種型別資料的操作。這個時候操作最多的就是針對該Object進行資料的強制轉換,而這種轉換是基於開發者對該資料型別明確的情況下進行的(比如將Object型轉換為String型)。倘若型別不一致,編譯器在編譯過程中不會報錯,但在執行時會出錯。

使用泛型的好處在於,它在編譯的時候進行型別安全檢查,並且在執行時所有的轉換都是強制的,隱式的,大大提高了程式碼的重用率。

二、定義&使用

型別引數的命名風格為:

推薦你用簡練的名字作為形式型別引數的名字(如果可能,單個字元)。最好避免小寫字母,這使它和其他的普通

的形式引數很容易被區分開來。

使用T代表型別,無論何時都沒有比這更具體的型別來區分它。這經常見於泛型方法。如果有多個型別引數,我們

可能使用字母表中T的臨近的字母,比如S。

如果一個泛型函式在一個泛型類裡面出現,最好避免在方法的型別引數和類的型別引數中使用同樣的名字來避免混

淆。對內部類也是同樣。

1.定義帶型別引數的類

在定義帶型別引數的.類時,在緊跟類命之後的<>內,指定一個或多個型別引數的名字,同時也可以對型別引數的取

值範圍進行限定,多個型別引數之間用,號分隔。

定義完型別引數後,可以在定義位置之後的類的幾乎任意地方(靜態塊,靜態屬性,靜態方法除外)使用型別引數,

就像使用普通的型別一樣。

注意,父類定義的型別引數不能被子類繼承。

public class TestClassDefine{ .... }

2.定義待型別引數方法

在定義帶型別引數的方法時,在緊跟可見範圍修飾(例如public)之後的<>內,指定一個或多個型別引數的名字,

同時也可以對型別引數的取值範圍進行限定,多個型別引數之間用,號分隔。

定義完型別引數後,可以在定義位置之後的方法的任意地方使用型別引數,就像使用普通的型別一樣。

例如:

publicT testGenericMethodDefine(T t, S s){ ... }

注意:定義帶型別引數的方法,騎主要目的是為了表達多個引數以及返回值之間的關係。例如本例子中T和S的繼

承關係, 返回值的型別和第一個型別引數的值相同。

如果僅僅是想實現多型,請優先使用萬用字元解決。萬用字元的內容見下面章節

publicvoid testGenericMethodDefine2(Lists){ ... }

應改為

public void testGenericMethodDefine2(List<?> s){ ... }

3. 型別引數賦值

當對類或方法的型別引數進行賦值時,要求對所有的型別引數進行賦值。否則,將得到一個編譯錯誤。

4.對帶型別引數的類進行型別引數賦值

對帶型別引數的類進行型別引數賦值有兩種方式

第一宣告類變數或者例項化時。例如

Listlist; list = new ArrayList;

第二繼承類或者實現介面時。例如

public class MyListextends ArrayListimplements List{...}

5.對帶型別引數方法進行賦值

當呼叫範型方法時,編譯器自動對型別引數進行賦值,當不能成功賦值時報編譯錯誤。例如

publicT testGenericMethodDefine3(T t, Listlist){ ... } publicT testGenericMethodDefine4(Listlist1, Listlist2){ ... } Number n = null; Integer i = null; Object o = null; testGenericMethodDefine(n, i);//此時T為Number, S為Integer testGenericMethodDefine(o, i);//T為Object, S為Integer Listlist1 = null; testGenericMethodDefine3(i, list1)//此時T為Number Listlist2 = null; testGenericMethodDefine4(list1, list2)//編譯報錯

6.萬用字元

在上面兩小節中,對是型別引數賦予具體的值,除此,還可以對型別引數賦予不確定值。例如

List unknownList; List unknownNumberList; List unknownBaseLineIntgerList;

注意: 在Java集合框架中,對於引數值是未知型別的容器類,只能讀取其中元素,不能像其中新增元素,

因為,其型別是未知,所以編譯器無法識別新增元素的型別和容器的型別是否相容,唯一的例外是NULL

ListlistString; List unknownList2 = listString; unknownList = unknownList2; listString = unknownList;//編譯錯誤

7.陣列範型

可以使用帶範型引數值的類宣告陣列,卻不可有建立陣列

List[] iListArray; new ArrayList[10];//編譯時錯誤

三、擴充套件

1、extends語句

使用extends語句將限制泛型引數的適用範圍。例如:

,則表示該泛型引數的使用範圍是所有實現了collection介面的calss。如果傳入一個則程式編譯出錯。

2、super語句

super語句的作用與extends一樣,都是限制泛型引數的適用範圍。區別在於,super是限制泛型引數只能是指定該class的上層父類。

例如,表示該泛型引數只能是List和List的上層父類。

3、萬用字元

使用萬用字元的目的是為了解決泛型引數被限制死了不能動態根據例項來確定的缺點。

舉個例子:public class SampleClass < T extends S> {…}

假如A,B,C,…Z這26個class都實現了S介面。我們使用時需要使用到這26個class型別的泛型引數。那例項化的時候怎麼辦呢?依次寫下

SampleClass a = new SampleClass();SampleClass a = new SampleClass();…SampleClassa = new SampleClass();

這顯然很冗餘,還不如使用Object而不使用泛型,呵呵,是吧?

彆著急,咱們使用萬用字元,就OK了。

SampleClass sc = new SampleClass();

只需要宣告一個sc變數,很方便把!