Java編程中有時我們要用到不確定的元素,通常用通配符"?"表示蜡秽,其中" ? extends T "叫"上界通配符", " ? super T "叫"下界通配符"漩仙。
PECS原則
PECS原則的全拼是"Producer Extends Consumer Super"搓茬。
當(dāng)需要頻繁取值,而不需要寫值則使用" ? extends T "作為數(shù)據(jù)結(jié)構(gòu)泛型队他。相反卷仑,當(dāng)需要頻繁寫值,而不需要取值則使用" ? super T "作為數(shù)據(jù)結(jié)構(gòu)泛型麸折。
使用示例
創(chuàng)建Apple锡凝,F(xiàn)ruit兩個類,其中Apple是Fruit的子類垢啼,寫如下測試代碼:
public class PECS {
ArrayList<? extends Fruit> exdentFurit;
ArrayList<? super Fruit> superFurit;
Apple apple = new Apple();
private void test() {
Fruit a1 = exdentFurit.get(0);
Fruit a2 = superFurit.get(0); //Err1
exdentFurit.add(apple); //Err2
superFurit.add(apple);
}
}
其中Err1和Err2行處報錯窜锯,因為這些操作并不符合PECS原則张肾,逐一分析:
Err1
對于使用" ? super T "規(guī)定泛型的數(shù)據(jù)結(jié)構(gòu),我們只知道其存儲的值是T的父類锚扎,若以T為數(shù)據(jù)類型取值時 T t = ?吞瞪,等于將父類(?)當(dāng)做子類(T)使用,這顯然是不合理的驾孔,父類缺少子類中的一些信息芍秆,因此編譯器直接禁止在使用" ? super T "泛型的數(shù)據(jù)結(jié)構(gòu)中進行取值,只能進行寫值翠勉,正是開頭所說的CS原則妖啥。Err2
使用" ? extends T "規(guī)定泛型的數(shù)據(jù)結(jié)構(gòu),我們知道其存儲的值是T的子類对碌,T可以有多個不同表現(xiàn)的子類(多態(tài))荆虱,因此當(dāng)我們進行寫值時,我們并不知道其中存儲的到底是哪個子類俭缓,不同子類是不同的類型克伊,因此寫值操作必然會出現(xiàn)問題,所以編譯器接禁止在使用" ? extends T "泛型的數(shù)據(jù)結(jié)構(gòu)中進行寫华坦,只能進行取值愿吹,正是開頭所說的PE原則。
總結(jié)
PECS原則惜姐,就是當(dāng)時用extends做泛型時犁跪,該數(shù)據(jù)結(jié)構(gòu)作為Producer對外提供值,只能進行取值而不能寫值歹袁。
當(dāng)時用super做泛型時坷衍,該數(shù)據(jù)結(jié)構(gòu)作為Producer對外提供值,只能進行取值而不能寫值条舔。 Consumer Super