Java泛型中的PECS原则

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java泛型中的PECS原则相关的知识,希望对你有一定的参考价值。

文章目录

PECS描述:

PECS原则的全拼是"Producer Extends Consumer Super"。

当需要频繁取值,而不需要写值则使用" ? extends T “作为数据结构泛型。相反,当需要频繁写值,而不需要取值则使用” ? super T "作为数据结构泛型。

例如:

List<? extends T>,你可以把这个List当成是一个生产者,可以从里面拿东西但是不能从里面放东西。也就是PE 只读。

List<? super T>,可以把这个List当成一个消费者,你可以往里面存数据,但是不能往里面获取数据。也就是SC 只写。

代码案例

package com.test;

import java.util.*;

/**
 * 定义三个父子类: Fruit -> Apple -> RedApple
 */
class Fruit


class Apple extends Fruit


class RedApple extends Apple


class Main
    /**
     * 代码验证
     * @param args
     */
    public static void main(String[] args) 
        /**
         *  1. List<? extends Apple> 必须使用 Apple的子类型List
         *  2. add()方法编译报错
         *  3. get()方法编译通过
         *
         *  理解: List<? extends Apple> 作为存储源可以确定上界但不能确定下界, [未知,Apple],因此,在进行元素添加的时候无法确定是Apple或者
         *      Apple的哪一个子类, 因此, 无法进行自动转型,不能 add();
         *
         *      但是再获取数据的时候, 能够明确数据肯定是 Apple或者 Apple的子类类型 [NULL, Apple], 因此,使用Apple进行接收即可, 可以 get()。
         *
         *  总结: PE (producer extends) 生产者使用 extends, 读多写少(生产者读取了才能进行生产)
         */
        //List<? extends Apple> apples = new ArrayList<Fruit>(); 编译报错
        //List<? extends Apple> apples = new ArrayList<Apple>(); 正确
        List<? extends Apple> apples = new ArrayList<RedApple>(); //正确
        apples.add(null); //正确
        apples.add(new Fruit()); //编译报错
        apples.add(new Apple()); //编译报错
        apples.add(new RedApple()); //编译报错

        //Fruit apple = apples.get(0); //正确
        Apple apple = apples.get(0); //正确


        /**
         *  1. List<? super Apple> 必须使用 Apple的父类型List
         *  2. add()方法编译通过
         *  3. get()方法编译通过
         *
         *  理解: List<? super Apple> 作为存储源可以确定下界但不能确定上界, [Apple,Object/未知],因此,在进行元素添加的时候可以添加Apple或者Apple的子类类型,因为数据存储源最小也是Apple类型,Apple和Apple的子类型可以自动向上转型为Apple和Apple的父类型; 但是再获取数据的时候, 就不能判断类型了,只能由Object最强顶级父类型来接收,因为存储的数据存储的范围为[NULL,Apple+]。
         *      因此,使用Apple进行接收即可, 可以 get()。
         *
         *  总结: CS (customer super) 消费使用 super, 写多读少(消费者消费了要进行写入)
         */
        //List<? extends Apple> apples2 = new ArrayList<Fruit>(); 编译报错
        //List<? extends Apple> apples2 = new ArrayList<Apple>(); 正确
        List<? super Apple> apples2 = new ArrayList<Fruit>(); //正确
        apples2.add(new RedApple()); //正确
        apples2.add(new Apple()); //正确
        //apples2.add(new Fruit()); 编译错误
        //Apple apple2 = apples2.get(0); //错误
        //Fruit apple2 = apples2.get(0); //错误
        Object apple2 = apples2.get(0); //正确
        apples2.get(1);
    


总结:

PE (producer extends) 生产者使用 extends, 上界确定,读取优良(用Apple接收),下界不定,写入不行(只能存null),读多写少(生产者读取了才能进行生产)

CS (customer super) 消费使用 super, 上界不定,读取不行(只能用Object接收),下界确定,写入优良(可以写入Apple与Apple的子类型),写多读少(消费者消费了要进行写入)

以上是关于Java泛型中的PECS原则的主要内容,如果未能解决你的问题,请参考以下文章

Java泛型中的PECS原则

Java泛型中的PECS原则

了解上界和下界?在 Java 泛型中

第六节:Java泛型

Java泛型中extends和super的区别

java泛型中extends 和 super的区别