java基础-泛型中的extends和super

List numbers = new ArrayList();

java的ArrayList有一个这样的构造函数

    public ArrayList(Collection c) {
      .......
    }

在不知道extends的作用的前提下,我们日常使用中就已经明白了这个构造函数的意思是传入一个Collection类型的集合,里面包含了我们声明的元素或者其子元素
用代码来说就是:

    ArrayList integers = new ArrayList<>();
    ArrayList doubles = new ArrayList<>();
    new ArrayList(integers);
    new ArrayList(doubles);

想在已有的List的基础上去创建一个包含Number的List,因为是包含Number的集合,所以理论上我我可以传入List,List这样的包含任一Number的子类的List。如果不去看源码的情况下,我们可能会很理想化的想到,ArrayList的这个构造函数是这样的:

public ArrayList(Collection c) { ....... }

代表我可以传入List,List。然而并不是。
因为在java里面,
List list = new ArrayList();
所以有了extends。

    List list;
    list = new ArrayList();
    list = new ArrayList();
    list = new ArrayList();

以上便是extends的作用,它表示声明的这个list 可以被赋予任何一种包含Number和Number子类的list
因为被赋予的List包含的必定是Number的子类,所以读出来的元素不论原本是Integer,Double,还是任一Number的子类,都可以像上转型为Number,所以下面的代码是没问题的。

Number item = list.get(0);

但是,当你add的时候,因为被赋予有可能是new ArrayList() ,new ArrayList()这些List中的任一一个,光靠声明的信息JVM在编译的时候是不知道具体是哪个list,那么你就不能往里面加元素。因为如果是赋予的一个new ArrayList(),而你add的是一个Double,那岂不是违反了泛型的基本语法,不允许不同类型的元素放入泛型容器中。

list.add(??????);

所以,当在声明的时候使用了extends,那么List就只能get,不能add了。
也即 extends 表示此list只能读。

super,同样的Demo:

    List list;
    list = new ArrayList();
    list = new ArrayList();
    list = new ArrayList();
 
 

上面这代码表示list表示可以被赋予任意一个装有Double或Double父类的list;
同理
读:
???? item = list.get(0);
这样是不行的,为啥?因为这个list是可能被赋予的list太广了。
如果是List list = new ArrayList();
那怎么可能知道你读出来的会是什么玩意儿?
写:

 list.add(new Double(1));

为啥这里可以写入呢?
因为不论赋予的是以下3种的任一一种集合,反正都是最少都是装Double的,所以一定可以装入Double,那么写入是可以的。

    list = new ArrayList();
    list = new ArrayList();
    list = new ArrayList();
 
 

所以使用了super的list没法读取,只能写入。

结合extends和super的特性,总结出来就是:PECS(Producer Extends, Consumer Super)

参考link:https://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java

你可能感兴趣的:(java基础-泛型中的extends和super)