泛型是什麼
泛型即參數化類型,就是將原來的具體的類型參數化。就像方法變量參數,類型也定義成類型參數,在傳入和調用的時候傳入具體的類型。看看下面的例子,有沒有什麼問題?
List arrayList = new ArrayList();
arrayList.add("hello");
arrayList.add(1);
for (int i = 0; i<arrayList.size();i++) {
System.out.println((String)arrayList.get(i));
}
ArrayList 可以存放任意類的值,上面的代碼中有Integer、String兩種類型,因爲沒有做參數類型限制,但是取出來當String類型使用的時候就會在運行時報錯:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
如果應用泛型,執行ArrayList類型爲String,List<String> arrayList = new ArraryList();可以在編譯階段就能發現錯誤,保證程序的健壯性。
泛型的使用
接下來我們從泛型類、泛型接口、泛型方法、泛型的通配符4個方面的介紹泛型的使用
泛型類
public class DataProcessor<T> {
T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
泛型類還是很簡單的,只要在類名後面加上類型參數即可,類型參數可以用任意的字母代替,常用的可以是T,E,K,V。在使用的時候只要傳入想要的具體的參數:
DataProcessor<String> data = new DataProcessor();
泛型接口
//定義一個泛型接口
public interface Generator<T> {
public T next();
}
這裏泛型接口有2點需要注意的點;
- 泛型接口沒有傳入泛型實參時,泛型接口的實現類也在定義時,也必須也泛型接口一樣將類型參數加到類中:
class FruitGenerator<T> implements Generator<T>{
@Override
public T next() {
return null;
}
}
- 泛型接口傳入具體的泛型實參,泛型接口的實現類也用到泛型的地方需要加上具體的類型如下:
class DataHolder implements Generator<String>{
@Override
public String next() {
return null;
}
}
泛型方法
首先泛型的方法是可以存在泛型類中,也是可以存在普通類中的,記住:能用泛型方法可以解決的問題,儘量使用泛型方法,下面用一個例子介紹泛型方法的使用:
class DataHolder<T>{
T item;
public void setData(T t) {
this.item=t;
}
public T getData() {
return this.item;
}
/**
* 泛型方法
* @param e
*/
public <E> void PrinterInfo(E e) {
System.out.println(e);
}
}
上面的例子中泛型類的類型參數T和泛型方法類型參數E,是沒有任何關係的。甚至都可以用T代替。PrinterInfo 的泛型方法的參數可以的String,Integer。泛型方法注意的幾點:
- public與返回值中間的<T>非常重要,可以理解爲聲明此方法爲泛型方法。
- 與泛型類的定義一樣,此處T可以隨便寫爲任意標識,常見的如T、E、K、V等形式的參數常用於表示泛型。
泛型上下邊界通配符
在使用泛型的時候,我們還可以爲傳入的泛型類型實參進行上下邊界的限制,如:類型實參只准傳入某種類型的父類或某種類型的子類
- 爲泛型添加上邊界,即傳入的類型實參必須是指定類型的子類型
public class DataProcessor<T extends Number> {
T data;
public T getData() {
return data;
}
public DataProcessor(T data) {
this.data = data;
}
public void setData(T data) {
this.data = data;
}
}
DataProcessor<Integer> d2 = new DataProcessor<>(12);
//這一行代碼編譯器會提示錯誤,因爲String類型並不是Number類型的子類
DataProcessor<String> d1 = new DataProcessor<String>("hello");
在來一個泛型參數的例子:
private <T extends Number> T show (DataProcessor<T> dataProcessor) {
System.out.println("container key :" + dataProcessor.getData());
T test = dataProcessor.data;
return test;
}
在泛型方法中添加上下邊界限制的時候,必須在權限聲明與返回值之間的<T>(或者是其它任意類型)上添加上下邊界,即在泛型聲明的時候添加.
總結
相信大家日常工作中肯定是經常用到泛型,尤其是集合的使用。有時候也會自定泛型來簡化代碼,一句話就是能用泛型就儘量用泛型。