參考: http://www.oracle.com/technetwork/cn/articles/java/juneau-generics-2255374-zhs.html
是什么
場(chǎng)景:希望有一個(gè)容器昂儒,可以接受任意類型
基本實(shí)現(xiàn)
文檔中首先提出了一種實(shí)現(xiàn)方式
public class ObjectContainer {
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
}
但是這種方式不是合適的解決方案合砂。這種方式不是類型安全的亡驰,且要求在檢索封裝的對(duì)象的時(shí)候使用顯示類型轉(zhuǎn)換。這就有可能引發(fā)異常
使用泛型來(lái)處理這種問(wèn)題
public class GenericContainer<T> {
private T obj;
public GenericContainer(){} //無(wú)參構(gòu)造
public GenericContainer(T t){ //有參構(gòu)造
obj = t;
}
public T getObj(){
return obj;
}
public void setObj(T t){
obj = t;
}
}
這時(shí)候栽连,不確定的類型就不是Object了险领,而是T,這是泛型類型
如果我們創(chuàng)建了一個(gè)這類容器秒紧,且指定了類型绢陌,那么就不能再在里面存放別的類型的對(duì)象
這里的描述我更傾向于:https://segmentfault.com/a/1190000005179142里面的說(shuō)法:
用一個(gè)類來(lái)包裝一個(gè)變量,但是我們不確定變量類型的時(shí)候使用泛型熔恢。也稱為[泛型類]脐湾。
使用泛型的好處
1.更強(qiáng)的類型檢查⌒鹛剩可以理解為因?yàn)橹付祟愋统诱疲捅苊饬似渌愋偷募尤氤钇蹋苊獍l(fā)生類型轉(zhuǎn)換錯(cuò)誤
2.因?yàn)橹付祟愋停幾g器明確知道集合中的數(shù)據(jù)類型闻鉴,我們就可以直接使用對(duì)象調(diào)用其方法:意思就是說(shuō)比如內(nèi)部是String類型茵乱,我們就可以直接拿對(duì)象調(diào)用String的方法,無(wú)需再進(jìn)行顯示類型轉(zhuǎn)換
如何使用泛型
上面的示例是生成泛型對(duì)象類型的用例
<T>是一個(gè)類型參數(shù)孟岛,表示在運(yùn)行時(shí)瓶竭,為這個(gè)類分配了這個(gè)類型,并且可以在整個(gè)類中使用
根據(jù)慣例渠羞,下面給出了常用的類型參數(shù):
- E:元素
- K:鍵
- N:數(shù)字
- T:類型
- V:值
- S斤贰、U、V 等:多參數(shù)情況中的第 2次询、3荧恍、4 個(gè)類型
泛型可以用于構(gòu)造函數(shù)的參數(shù)中,限制參數(shù)類型
如果一個(gè)類有多個(gè)類型參數(shù)渗蟹,聲明的時(shí)候块饺,類型參數(shù)之間使用“赞辩,”分隔雌芽,如:
public class GenericContainer<T,S,E> {...}
這個(gè)就表示我這個(gè)類可以接收多個(gè)類型的參數(shù)
有界類型
情況是,我們希望控制類型參數(shù)的范圍辨嗽,而不是任何類型世落,常用方式就是在類型參數(shù)部分使用extends或super關(guān)鍵字,限制泛型類型的邊界
比如:
//表示類型參數(shù)T屬于Number的子類糟需,指定了類型參數(shù)的上界
public class GenericNumberContainer <T extends Number>{...}
//這個(gè)我暫時(shí)沒(méi)有找到例子屉佳,按照上面的理解就是這個(gè)泛型類型是T的父
//類,對(duì)應(yīng)的洲押,也就指定了類型參數(shù)的下界武花,至少也要是T的父類,待證
public class XXX<? super T>{...}
泛型方法
- 有時(shí)我們不知道方法將接受的類型杈帐,就可以在參數(shù)中使用泛型体箕。
- 方法的返回類型也可以是泛型類型
在參數(shù)中使用泛型:
注意:我們要在返回值之前聲明泛型類型,才能在參數(shù)中使用泛型類型
public <T> void getObj(T n){
//...
}
public static <N extends Number> double add(N a,N b){
double sum =0;
sum = a.doubleValue()+b.doubleValue();
return sum;
}
返回泛型類型
這里也需要在返回值之前聲明泛型類型
public <T> T getObj(T n){
return n;
}
所以挑童,我們?cè)诜椒ㄖ行枰褂玫椒盒偷臅r(shí)候都要在返回值之前聲明泛型類型
通配符
這里的通配符是指使用<?>來(lái)替代<T>
不推薦在返回值使用通配符累铅,這樣不安全
通配符一樣可以使用extends或者super來(lái)限制上界和下界