在Java SE1.5中, 增加了一個新的特性:泛型(日本語中的總稱型)。何謂泛型呢?通俗的說,就是泛泛的指定對象所操作的類型,而不像常規方式一樣使用某種固定的類型去指定。
泛型的本質就是將所操作的數據類型參數化,也就是說,該數據類型被指定為一個參數。這種參數類型可以使用在類、接口以及方法定義中。
一、為什么使用泛型呢?
在以往的J2SE中,沒有泛型的情況下,通常是使用Object類型來進行多種類型數據的操作。這個時候操作最多的就是針對該Object進行數據的強制轉換,而這種轉換是基于開發者對該數據類型明確的情況下進行的(比如將Object型轉換為String型)。倘若類型不一致,編譯器在編譯過程中不會報錯,但在運行時會出錯。
使用泛型的好處在于,它在編譯的時候進行類型安全檢查,并且在運行時所有的轉換都是強制的,隱式的,大大提高了代碼的重用率。
二、
泛型的簡單例子:
首先,我們來看看下面兩個普通的class定義
public class
getString {
private String myStr;
public String getStr() {
return myStr;
}
public void setStr(str) {
myStr = str;
}
}
public class
getDouble {
private Double myDou;
public Double getDou() {
return myDou;
}
public void setDou(dou) {
myDou = dou;
}
}
這兩個class除了所操作的數據類型不一致,其他機能都是相同的。現在,我們可以使用泛型來將上面兩個class合并為一個,從而提高代碼利用率,減少代碼量。
public class getObj<T> {
private T myObj ;
public T getObj() {
return myObj;
}
public void setObj<T obj> {
myObj = obj;
}
}
那么,使用了泛型后,如何生成這個class的實例來進行操作呢?請看下面的代碼:
getObj<String> strObj = new getObj<String>();
strObj.setObj(“Hello Nissay”);
System.out.println(strObj.getObj());
getObj<Double> douObj = new getObj<Double>();
douObj.setObj(new Double(“116023”));
System.out.println(douObj.getObj());
三、例子分析
現在我們來分析上面那段藍色字體的代碼:
1、<T>是泛型的標記,當然可以使用別的名字,比如。使用<T>聲明一個泛型的引用,從而可以在class、方法及接口中使用它進行數據定義,參數傳遞。
2、<T>在聲明的時候相當于一個有意義的數據類型,編譯過程中不會發生錯誤;在實例化時,將其用一個具體的數據類型進行替代,從而就可以滿足不用需求。
四、泛型的規則和限制
通過上述的例子,我們簡單理解了泛型的含義。在使用泛型時,請注意其使用規則和限制,如下:
1、泛型的參數類型只能是類(class)類型,而不能是簡單類型。
比如,<int>是不可使用的。
2、可以聲明多個泛型參數類型,比如<T, P,Q…>,同時還可以嵌套泛型,例如:<List<String>>
3、泛型的參數類型可以使用extends語句,例如<T extends superclass>。
4、泛型的參數類型可以使用super語句,例如< T super childclass>。
5、泛型還可以使用通配符,例如<? extends
ArrayList>
五、
擴展
1、extends語句
使用extends語句將限制泛型參數的適用范圍。例如:
<T extends
collection> ,則表示該泛型參數的使用范圍是所有實現了collection接口的calss。如果傳入一個<String>則程序編譯出錯。
2、super語句
super語句的作用與extends一樣,都是限制泛型參數的適用范圍。區別在于,super是限制泛型參數只能是指定該class的上層父類。
例如<T super
List>,表示該泛型參數只能是List和List的上層父類。
3、通配符
使用通配符的目的是為了解決泛型參數被限制死了不能動態根據實例來確定的缺點。
舉個例子:public
class SampleClass < T extends S> {…}
假如A,B,C,…Z這26個class都實現了S接口。我們使用時需要使用到這26個class類型的泛型參數。那實例化的時候怎么辦呢?依次寫下
SampleClass<A>
a = new SampleClass();
SampleClass<B>
a = new SampleClass();
…
SampleClass<Z>
a = new SampleClass();
這顯然很冗余,還不如使用Object而不使用泛型,呵呵,是吧?
別著急,咱們使用通配符,就OK了。
SampleClass<?
Extends S> sc = new SampleClass();