美文网首页
java基础-泛型中的extends和super

java基础-泛型中的extends和super

作者: lazyguy | 来源:发表于2017-10-25 16:04 被阅读0次

    List<Number> numbers = new ArrayList<Integer>();

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

        public ArrayList(Collection<? extends E> c) {
          .......
        }
    

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

        ArrayList<Integer> integers = new ArrayList<>();
        ArrayList<Double> doubles = new ArrayList<>();
        new ArrayList<Number>(integers);
        new ArrayList<Number>(doubles);
    

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

    public ArrayList(Collection<E> c) { ....... }
    

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

        List<? extends Number> list;
        list = new ArrayList<Number>();
        list = new ArrayList<Integer>();
        list = new ArrayList<Double>();
    

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

    Number item = list.get(0);
    

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

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

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

    super,同样的Demo:

        List<? super Double> list;
        list = new ArrayList<Double>();
        list = new ArrayList<Number>();
        list = new ArrayList<Object>();
    

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

     list.add(new Double(1));
    

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

        list = new ArrayList<Double>();
        list = new ArrayList<Number>();
        list = new ArrayList<Object>();
    

    所以使用了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

          本文链接:https://www.haomeiwen.com/subject/tkmqpxtx.html