Java 5 之后提供泛型(Generics)支持,使用泛型可以最大限度地重用代碼、保護(hù)類型的安全以及提高性能。泛型特性對(duì) Java 影響最大是集合框架的使用。
對(duì)于 Java 5 之前程序員而言,使用集合經(jīng)常會(huì)面臨一個(gè)很尷尬的問題:放入一個(gè)種特定類型,但是取出時(shí)候全部是 Object 類型,于是在具體使用時(shí)候需要將元素強(qiáng)轉(zhuǎn)換為特定類型。但是強(qiáng)制類型轉(zhuǎn)換是有風(fēng)險(xiǎn)的,如果不進(jìn)行判斷就臆斷進(jìn)行類型轉(zhuǎn)換會(huì)發(fā)生 ClassCastException 異常。
而泛型的引入可以將這些運(yùn)行時(shí)異常提前到編譯期暴露出來,這增強(qiáng)了類型安全檢查。
自定義泛型類
public class Queue<T> {
// 聲明保存隊(duì)列元素集合items
private List<T> items;
// 構(gòu)造方法初始化是集合items
public Queue() {
this.items = new ArrayList<T>();
}
/**
* 入隊(duì)方法
* @param item 參數(shù)需要入隊(duì)的元素
*/
public void queue(T item) {
this.items.add(item);
}
/**
* 出隊(duì)方法
* @return 返回出隊(duì)元素
*/
public T dequeue(){
if (items.isEmpty()) {
return null;
} else {
return this.items.remove(0);
}
}
@Override
public String toString() {
return items.toString();
}
}
T 是什么呢?T 表示類型參數(shù),泛型就是類型參數(shù)化,處理的數(shù)據(jù)類型不是固定的,而是可以作為參數(shù)傳入。
泛型的好處既然只使用普通類和 Object 就可以,而且泛型最后也轉(zhuǎn)換為了普通類,那為什么還要用泛型呢?或者說,泛型到底有什么好處呢?泛型主要有兩個(gè)好處:
? 更好的安全性。
? 更好的可讀性。
語言和程序設(shè)計(jì)的一個(gè)重要目標(biāo)是將 bug 盡量消滅在搖籃里,能消滅在寫代碼的時(shí)候,就不要等到代碼寫完程序運(yùn)行的時(shí)候。只使用 Object,代碼寫錯(cuò)的時(shí)候,開發(fā)環(huán)境和編譯器不能幫我們發(fā)現(xiàn)問題。
自定義泛型
自定義泛型接口與自定義泛型類類似,定義的方式完全一樣。
泛型方法
在方法中也可以使用泛型,即方法的參數(shù)類型或返回值類型,可以用類型參數(shù)表示。實(shí)現(xiàn)代碼如下:
// 限定類型參數(shù)為 Number
public static <T> boolean isEquals(T a, T b) {
return a.equals(b);
}
另外,泛型的類型參數(shù)也可以限定一個(gè)邊界,例如比較方法 isEquals() 只想用于數(shù)值對(duì)象大小的比較,實(shí)現(xiàn)代碼如下:
// 限定類型參數(shù)為Number
public static <T extends Number> boolean isEquals(T a, T b) {
return a.equals(b);
}
泛型通配符
泛型方法到底應(yīng)該用通配符的形式還是加類型參數(shù)。兩者到底有什么關(guān)系?
1)通配符形式都可以用類型參數(shù)的形式來替代,通配符能做的,用類型參數(shù)都能做。
2)通配符形式可以減少類型參數(shù),形式上往往更為簡(jiǎn)單,可讀性也更好,所以,能用通配符的就用通配符。
3)如果類型參數(shù)之間有依賴關(guān)系,或者返回值依賴類型參數(shù),或者需要寫操作,則只能用類型參數(shù)。
4)通配符形式和類型參數(shù)往往配合使用,比如,上面的 copy 方法,定義必要的類型參數(shù),使用通配符表達(dá)依賴,并接受更廣泛的數(shù)據(jù)類型。