java PECS以及 通配符? 和T

首先说一下PECS 原则,有过写泛型代码的朋友对此都不陌生,今天也遇到类似的问题,简单记录一下。

1.如果要从集合中读取类型T数据,并且不能写入,可以使用 ? extends E 通配符 ;接受E类型或者E的子类型

2.如果要向集合里写入类型T数据,并且不需要读取, 可以使用 ? super E 通配符; 接收E类型或者E的父类型

3.如果既要存又要取,那么就不要使用任何通配符

具体测试代码如下:

import java.util.ArrayList;
import java.util.List;

/**
 * Created by passself on 2018/8/2.
 */
public class PECS {
    static class Food{}
    static class Fruit extends Food{}
    static class Apple extends Fruit{}

    public static void main(String[] args) {
        List fruits = null;//new ArrayList<>();//编译错误
        //fruits.add(new Food());
        //fruits.add(new Fruit());
        //fruits.add(new Apple());//编译器只是知道fruits 是Fruit 的某个子类,并不知道这个子类具体是什么,为了类型安全,只好阻止向其中加入任何类型
        fruits = new ArrayList();
        fruits = new ArrayList();
        //fruits.add(new Fruit());
        //fruits = new ArrayList();//编译错误

        //fruits = new ArrayList();

        Food food = fruits.get(0);

        //使用super 效果 表示类型的下界是 T,参数化类型可以是 T 或 T 的超类:
        List tempFruits = null;
        tempFruits = new ArrayList();
        tempFruits = new ArrayList();
        //tempFruits = new ArrayList();//编译错误

        tempFruits.add(new Fruit());
        tempFruits.add(new Apple());
        //tempFruits.add(new Food());//编译错误,出于对类型安全的考虑(编译器会自动向上转型),只能加入fruit或者其子类,因为不知道是哪个超类

        //Fruit fruit = tempFruits.get(0); //编译错误 编译器并不知道超类具体是什么类,只能返回Object对象,因为Object是任何java类的超类
        Object object = tempFruits.get(0);


    }

    /**
     * 说明:
     * 如果要从集合中读取类型T数据,并且不能写入,可以使用 ? extends E 通配符 ;接受E类型或者E的子类型
     * 如果要向集合里写入类型T数据,并且不需要读取, 可以使用 ? super E 通配符; 接收E类型或者E的父类型
     * 如果既要存又要取,那么就不要使用任何通配符
     */
}

其中注释部分是无法编译成功的,也标注相关解释。

补充:

上面正好提到了通配符?来看一下和我们常用的 T通配符的区别.
? 代表不清楚到底是怎样的类型
T 是限定了相关的类型"T"
比如:
List al=new ArrayList();指定集合元素只能是T类型
List al=new ArrayList(); 只是知道是E的子类,并不知道是哪个子类,?通配符一般不单独使用,因为单独使用也没有意义,比如:List al=new ArrayList();
使用方式有? extends E 或者? super E

你可能感兴趣的:(java PECS以及 通配符? 和T)