天天看點

Java 泛型的讀寫規則:PECS

PECS 是 “Producer Extends Consumer Super” 的縮寫,是 Java 泛型中的重要用法。

PECS 就是當你需要周遊某一個類型和子類的集合資料時,集合相當于生産者,此時泛型使用 ​

​<? extends T>​

​​。當需要往某個類型的集合添加類和子類執行個體時,集合相當于消費者,此時泛型使用 ​

​<? super T>​

​。

Java 泛型的讀寫規則:PECS
每年八九月份的瓜是最甜的。

PECS

對 Java 泛型 PECS 的講解中,大多是從參數使用的角度來的,本文結合調用傳值和參數使用對比來看 PECS 的兩種情況。

Java 泛型的讀寫規則:PECS

PE

當我們想要周遊讀取某個集合時,需要使用 ​

​<? extends T>​

​,用上面類型為例,為了友善檢視編譯時的錯誤,直接上截圖:

Java 泛型的讀寫規則:PECS

當使用​

​<? extends Watermelon>​

​​,類型的上限是 ​

​Watermelon​

​​,從集合取出的值預設就是 ​

​Watermelon​

​​,是以也能用父類定義去引用,是以方法前三個指派正确,​

​KylinWatermelon​

​​ 錯誤。此時的集合除了可以 ​

​add(null)​

​ 外,不能添加任何其他類型,為什麼不能添加?我們從調用方看看:

Java 泛型的讀寫規則:PECS

調用方中,方法的參數不能是 ​

​Object​

​​ 和 ​

​Fruit​

​​ 的集合,可以是 ​

​Watermelons​

​​ 和子類 ​

​KylinWatermelon​

​​,當這倆作為參數傳遞進去時,不能往 ​

​List<Watermelon>​

​​ 中添加 ​

​Object, Fruit​

​​,不能往 ​

​List<KylinWatermelon>​

​​中添加 ​

​Object, Fruit,Watermelon​

​​。由于參數的類型不确定,是以除了​

​null​

​​,其他都不能 ​

​add​

​。

CS

當需要往某個類型的集合添加類和子類執行個體時,集合相當于消費者,此時泛型使用 ​

​<? super T>​

​。

Java 泛型的讀寫規則:PECS

當使用​

​<? super Watermelon>​

​​,類型的下限是 ​

​Watermelon​

​。為了友善了解編譯錯誤的原因,先看如何調用的方法:

Java 泛型的讀寫規則:PECS

源碼

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());
    }
}