開心一笑
【女:“一天中最幸福的時(shí)刻就是下班后你騎自行車載著我到街角那邊吃鹵肉飯转锈。”
男:“說實(shí)話楚殿〈榭”
女:“你騎自行車載我去吃鹵肉飯±漳В”
男:“說實(shí)話甫煞。”
女:“鹵肉飯……”】
**提出問題******
java開發(fā)中如何更好使用范型???
解決問題
以下來自《Effective Java》讀書筆記:
請(qǐng)不要在新代碼中使用原生態(tài)類型
參考高手文章:
http://www.cnblogs.com/nayitian/archive/2013/08/08/3245496.html
http://www.cnblogs.com/TwoWaterLee/p/5878056.html
參數(shù)化類型冠绢,通配符類型和原生態(tài)類型對(duì)比:
- Set<Object>是個(gè)參數(shù)化類型抚吠,表示可以包含任何對(duì)象的一個(gè)集合;
- Set<?>則是一個(gè)通配符類型弟胀,表示只能包含某種未知對(duì)象類型的一個(gè)集合楷力;
- Set則是個(gè)原生態(tài)類型,它脫離了泛型系統(tǒng)孵户。**前兩種是安全的萧朝,最后一種不安全。
無限制通配類型和原生態(tài)類型的區(qū)別是:通配符類型是安全的夏哭,原生態(tài)類型不安全检柬。你可以將任何元素放入到原生態(tài)類型的集合中,但不能將除了null之外的其他任何元素放到Collection<?>中竖配。
例如:
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
unsafeAdd(strings, new Integer(42));
String s = strings.get(0); // Compiler-generated cast
}
//重點(diǎn)在這里何址。list參數(shù)是原生態(tài)類型里逆,整個(gè)編譯過程都不會(huì)出現(xiàn)問題,但是運(yùn)行時(shí)候就是會(huì)報(bào)ClassCastException異常
private static void unsafeAdd(List list, Object o) {
list.add(o);
}
兩條例外:
- a.在Class中只能使用原生態(tài)類型用爪,因?yàn)榉盒托畔⒖梢栽谶\(yùn)行時(shí)被擦除原押。
- b.在操作instanceof時(shí),使用參數(shù)化類型非法偎血。
消除非受檢警告
參考高手文章:
http://blog.csdn.net/lqadam/article/details/52563155
要盡可能地消除每一個(gè)非受檢的警告诸衔。
使用@SuppressWarnings("unchecked")注解,需要注意的是將該注解用在盡可能小的范圍內(nèi)颇玷,能在變量上使用的不在方法上使用笨农,能在方法上使用的不在類上使用。
使用@SuppressWarnings注解時(shí)亚隙,都要添加一條注釋磁餐,說明為什么這么做是類型安全的
列表優(yōu)先于數(shù)組
下面的代碼片段是合法的,卻是不符合預(yù)期:
// 運(yùn)行時(shí)候失敗
Object[] objectArray = new Long[1];
objectArray[0] = “I don’t fit in”; // Throws ArrayStoreException
但下面這段代碼則不合法阿弃,但卻提醒了你怎樣才能達(dá)到預(yù)期:
// Won’t compile!
List<Object> o1 = new ArrayList<Long>(); // Incompatible types
o1.add(“I don’t fit in”);
明顯诊霹,利用列表可以在編譯時(shí)發(fā)現(xiàn)錯(cuò)誤。我們當(dāng)然希望在編譯時(shí)發(fā)現(xiàn)錯(cuò)誤了渣淳。
總結(jié):數(shù)組是協(xié)變的脾还,數(shù)組是具體化的:在運(yùn)行時(shí)才知道并檢查它們的元素類型約束。
優(yōu)先考慮泛型入愧,優(yōu)先考慮范型方法
定義泛型方法語(yǔ)法格式如下:
http://www.cnblogs.com/iyangyuan/archive/2013/04/09/3011274.html
參考高手文章:
http://www.cnblogs.com/cutter-point/p/5883279.html
修改前:
//這里使用原生類型是不合理的
public static Set union1(Set s1, Set s2){
Set result = new HashSet(s1);
result.addAll(s2);
return result;
}
修改后:
//這里的范型沒有安全警告
public static <E> Set<E> union(Set<E> s1, Set<E> s2){
Set<E> result = new HashSet<E>(s1);
result.addAll(s2);
return result;
}
利用有限制通配符來提升API的靈活性
參考高手文章:
http://www.cnblogs.com/13jhzeng/p/5726511.html
先看下面例子:
修改之前:
public void pushAll(Iterable<E> src) {
for (E e : src) {
push(e)
}
}
修改之后:
//src是生成者鄙漏,所以使用extend
public void pushAll(Iterable<? extends E> src) {
for (E e : src) {
push(e)
}
}
pushAll的輸入?yún)?shù)類型不應(yīng)該為"E的Iterable接口",而應(yīng)該為"E的某個(gè)子類型的Iterable接口"棺蛛,有一個(gè)通配符類型正符全此意:Iterable<? Extends E>
PECS 表示:producer-extends, consumer-super
如果參數(shù)化類型表示一個(gè)T生產(chǎn)者怔蚌,就使用<? extends T>;如果它表示一個(gè)T消費(fèi)者旁赊,就使用<? super T>桦踊。如果使用得當(dāng),通配符類型對(duì)于類的用戶來說幾乎是無形的终畅。它們使方法能夠接受它們應(yīng)該接受的參數(shù)籍胯,并拒絕那些應(yīng)該拒絕的參數(shù)。如果類的用戶必須考慮通配符類型离福,類的API也許就會(huì)出錯(cuò)杖狼。
假設(shè)添加一個(gè)popAll方法,從堆棧中彈出每個(gè)元素妖爷,添加到指定集合中:
修改前
public void popAll(Collection<E> dst) {
while(!isEmpty) {
dst.add(pop());
}
}
與未修改的putAll一樣蝶涩,應(yīng)當(dāng)允許類型為Number的棧幀放在包括Number在內(nèi)的父類型中。所以,修改為:
修改后
public void popAll(Collection<? super E> dst) {
while(!isEmpty) {
//這里dst是消費(fèi)者子寓,所以使用super
dst.add(pop());
}
}
總之暗挑,如果參數(shù)化類型表示一個(gè)T生產(chǎn)者,就使用<? extends T>斜友,如果表示一個(gè)T的消費(fèi)者,就使用<? super T>
優(yōu)先考慮類型安全的異構(gòu)容器
參考高手文章:
http://blog.csdn.net/zhang_amao/article/details/52107612
http://blog.csdn.net/tkd03072010/article/details/7722110
public Class Favorites{
public <T> void putFavorite(Class<T> type, T instance);
public <T> T getFavorites(Class<T> type);
}
Favorites實(shí)例是類型安全的:當(dāng)你向它請(qǐng)求String的時(shí)候垃它,不會(huì)返回一個(gè)Integer給你鲜屏。同時(shí)它也是異構(gòu)的:不像普通的map,它的所有的鍵都是不同類型的国拇。因此洛史,我們將Favorites稱作類型安全的異構(gòu)容器
Map不能保證鍵和值之間的類型關(guān)系,即不能保證每個(gè)值的類型都與鍵的類型相同酱吝,當(dāng)你考慮到這個(gè)問題時(shí)也殖,可以嘗試使用類型安全的異構(gòu)容器:
public class Favorites {
private Map<Class<?>, Object> favorites =
new HashMap<Class<?>, Object>();
public <T> void putFavorites(Class<T> type, T instance) {
if(type == null)
throw new NullPointerException();
favorites.put(type, type.cast(instance));
}
public <T> T getFavorites(Class<T> type) {
return type.cast(favorites.get(type));
}
}
讀書感悟
來自三毛《稻草人手記》
- 我們還年輕,長(zhǎng)長(zhǎng)的人生可以受一點(diǎn)風(fēng)浪务热。
- 我喜歡看見幸福的人忆嗜,不管他們結(jié)不結(jié)婚。
- 快回來吧崎岂!我希望把有生之年都靜靜地跟你分享捆毫。短短的人生我們不要再分開了啊。
- 肉體的軟弱是一時(shí)的 精神的勝利是永久的
- 自由是多么可貴的事冲甘,心靈的自由更是我們要牢牢把握住的绩卤;不然,有了愛情仍是不夠的江醇。
其他
如果有帶給你一絲絲小快樂濒憋,就讓快樂繼續(xù)傳遞下去,歡迎轉(zhuǎn)載陶夜,點(diǎn)贊凛驮,頂,歡迎留下寶貴的意見律适,多謝支持辐烂!