PECS 是 “Producer Extends Consumer Super” 的縮寫,是 Java 泛型中的重要用法。
PECS 就是當你需要周遊某一個類型和子類的集合資料時,集合相當于生産者,此時泛型使用
<? extends T>
。當需要往某個類型的集合添加類和子類執行個體時,集合相當于消費者,此時泛型使用
<? super T>
。

每年八九月份的瓜是最甜的。
PECS
對 Java 泛型 PECS 的講解中,大多是從參數使用的角度來的,本文結合調用傳值和參數使用對比來看 PECS 的兩種情況。
PE
當我們想要周遊讀取某個集合時,需要使用
<? extends T>
,用上面類型為例,為了友善檢視編譯時的錯誤,直接上截圖:
當使用
<? extends Watermelon>
,類型的上限是
Watermelon
,從集合取出的值預設就是
Watermelon
,是以也能用父類定義去引用,是以方法前三個指派正确,
KylinWatermelon
錯誤。此時的集合除了可以
add(null)
外,不能添加任何其他類型,為什麼不能添加?我們從調用方看看:
調用方中,方法的參數不能是
Object
和
Fruit
的集合,可以是
Watermelons
和子類
KylinWatermelon
,當這倆作為參數傳遞進去時,不能往
List<Watermelon>
中添加
Object, Fruit
,不能往
List<KylinWatermelon>
中添加
Object, Fruit,Watermelon
。由于參數的類型不确定,是以除了
null
,其他都不能
add
。
CS
當需要往某個類型的集合添加類和子類執行個體時,集合相當于消費者,此時泛型使用
<? super T>
。
當使用
<? super Watermelon>
,類型的下限是
Watermelon
。為了友善了解編譯錯誤的原因,先看如何調用的方法:
源碼
public class PECSLearn {
public static class Fruit {}
public static class Watermelon extends Fruit {}
public static class KylinWatermelon extends Watermelon {}
public static void main(String[] args) {
List<Object> objects = Arrays.asList(new Object());
List<Fruit> fruits = Arrays.asList(new Fruit());
List<Watermelon> watermelons = Arrays.asList(new Watermelon());
List<KylinWatermelon> kylinWatermelons = Arrays.asList(new KylinWatermelon());
producer(objects);//編譯錯誤
producer(fruits);//編譯錯誤
producer(watermelons);
producer(kylinWatermelons);
consumer(objects);
consumer(fruits);
consumer(watermelons);
consumer(kylinWatermelons);//編譯錯誤
}
public static void producer(List<? extends Watermelon> watermelons) {
Object object = watermelons.get(0);
Fruit fruit = watermelons.get(0);
Watermelon watermelon = watermelons.get(0);
KylinWatermelon kylinWatermelon = watermelons.get(0);//編譯錯誤
watermelons.add(null);
watermelons.add(new Object());//編譯錯誤
watermelons.add(new Fruit());//編譯錯誤
watermelons.add(new Watermelon());//編譯錯誤
watermelons.add(new KylinWatermelon());//編譯錯誤
}
public static void consumer(List<? super Watermelon> watermelons) {
Object object = watermelons.get(0);
Fruit fruit = watermelons.get(0);//編譯錯誤
Watermelon watermelon = watermelons.get(0);//編譯錯誤
KylinWatermelon kylinWatermelon = watermelons.get(0);//編譯錯誤
watermelons.add(new Object());//編譯錯誤
watermelons.add(new Fruit());//編譯錯誤
watermelons.add(new Watermelon());
watermelons.add(new KylinWatermelon());
}
}