????在工作中經(jīng)常會使用到泛型,所以整理一些泛型相關(guān)的資料,一起理解,學(xué)習(xí)一下。
1.泛型是什么,解決了什么問題。
????泛型又叫參數(shù)化類型,就是將類型像參數(shù)一樣傳遞,可以在類,接口,方法中使用。在調(diào)用時,傳遞具體的類型。它可以提高代碼的可重用性,讓我們可以方便的實現(xiàn)一些通用算法,還可以提供更強大的類型檢查,在編譯階段就可以發(fā)現(xiàn)代碼的安全性錯誤,相比運行時才發(fā)現(xiàn)錯誤,可以讓我們更好的定位,修復(fù)錯誤。
2.泛型的三種使用方式
2.1 泛型類
泛型類通過在類名后加上一對尖括號 <T,T...>來定義,下面看代碼:
class ClassName<T>{/* ... */}
????括號中的內(nèi)容,就是指定的類型參數(shù)。通常類型參數(shù)名稱是單個大寫字母。最常用的類型參數(shù)名稱是:
- E - 元素(由 Java 集合框架廣泛使用)
- K - Key
- N - Number
- T - Type
- V - Value
- S,U,V etc. - 2nd, 3rd, 4th types
下面是一個最簡單的泛型類:
public class Generics<T> {
private T t; /* 泛型成員變量 */
/* 泛型成員方法(無返回值) */
public void set(T t) {
this.t = t;
}
/* 泛型成員方法(有返回值) */
public T get() {
return t;
}
}
上面Generics類中的<T>就是要傳入的參數(shù),下面看看泛型類是怎樣調(diào)用/實例化的。
Generics<Integer> gInt = new Generics<Integer>();
上面例子中的Integer類型,就像參數(shù)一樣傳遞給了Generics類。
需要注意的是,在泛型類中,不可以聲明類型為,類型參數(shù)的靜態(tài)字段:
public class Generics<T> {
private static T t; /* error 編譯時會報錯*/
}
如果Java允許這樣聲明,那么我們看看下面的例子:
Generics<Integer> gInt = new Generics<Integer>();
Generics<String> gString = new Generics<String>();
Generics<Double> gDouble= new Generics<Double>();
因為靜態(tài)字段會被以上三個對象共享,所以它的類型是什么呢?因此,不可以聲明類型為,類型參數(shù)的靜態(tài)字段。
2.1.1 原生類型(raw type)
原生類型就是一個泛型類在我們在使用時,沒有傳遞類型參數(shù)。下面看一個例子:
public class Generics<T> {
private T t; /* 泛型成員變量 */
}
我們正常實例化這個類時會傳遞類型參數(shù):
Generics<Integer> gInt = new Generics<Integer>();
下面是原生類型,調(diào)用時不傳遞參數(shù)類型:
Generics g = new Generics();
????原生類型是Java在推出了泛型后,為了兼容過去的代碼而產(chǎn)生的。所以Java為了向后兼容,允許將參數(shù)化類型分配給它的原生類型:
Generics<Integer> gInt = new Generics<Integer>(); /* 參數(shù)化類型*/
Generics g = gInt; /* 原生類型*/
如果將原生類型分配給參數(shù)化類型會收到一個警告:
Generics g = new Generics(); /* 原生類型*/
Generics<Integer> gInt = g; /* 警告:未經(jīng)檢查的類型轉(zhuǎn)換 */
如果使用原生類型去調(diào)用對應(yīng)泛型中的方法只會得到一個警告:
Generics<Integer> gInt = new Generics<Integer>();
Generics g = gInt;
g.set("a");
這種調(diào)用方式會繞過泛型的類型檢查,代碼的安全性錯誤會在運行時才能發(fā)現(xiàn)。所以盡量不要使用原生類型。