zoukankan      html  css  js  c++  java
  • Java泛型通配符

    前言

    String是Object的子类,因此下面的代码是合法的。

    Object obj = new String();
    

    但是,下面这段代码是不合法的。

    ArrayList<Object> list = new ArrayList<String>();
    

    原因就是,泛型是不变的(invariant)。泛型通配符就是解决这一问题的,可以增大代码的灵活性。

    <? extends E>

    <? extends E>是上限通配符,限定了类型的上限(这里的上,指的的是类继承图中的位置),?必须是E的子类。
    以下图的继承关系为例,这些代码都是合法的。

    ArrayList<? extends animal> list = new ArrayList<animal>();
    ArrayList<? extends animal> list = new ArrayList<cat>();
    ArrayList<? extends animal> list = new ArrayList<dog>();
    

    存入元素

    由于<? extends E>只指定了类型的上限,因此,list中存放的是E的子类,但编译器无法确定是哪个子类,因此无法加入元素。例如:

    ArrayList<? extends animal> list = new ArrayList<cat>();
    list.add(new dog());
    

    虽然dog是animal的子类,但是,此时的list实际上是指向ArrayList的,那么必然会引起错误。

    取得元素

    由于<? extends E>指定了类型的上限,因此,我们获得的所有元素,都是animal的子类,因此下面的语句是合法的。

    ArrayList<? extends animal> list = new ArrayList<cat>();
    animal t = list.get(0);
    

    <? super E>

    <? super E>是上限通配符,限定了类型的上限,?必须是E的父类。

    存入元素

    list中存放的是E或E的父类,因此,list是一定可以存储EE的子类的。因此下面的代码是合法的。

    ArrayList<? super dog> list = new ArrayList<animal>();
    list.add(new dog());
    

    取得元素

    list中存放的是E或E的父类,因此,我们只能确定,我们所取得的元素是Object的子类。因此下面的代码是合法的。

    ArrayList<? super dog> list = new ArrayList<animal>();
    Object obj = list.get(0);
    

    PECS法则

    PECS是"Producer-extends, Consumer-super"的简写。
    我们看到,<? extends E>适合于取元素的场景(生产者);<? super E>可以存入E类型的数据,适合于取元素的场景(消费者)。
    如果是既要存、也要取的集合,那么不适合使用泛型通配符。

  • 相关阅读:
    GO语言网络编程
    GO语言测试
    GO语言反射
    GO语言strconv包的使用
    GO语言并发
    Centos7 开启swap分区
    设计模式 之 命令模式
    设计模式 之 代理模式
    设计模式 之 工厂模式
    设计模式 之 观察者模式
  • 原文地址:https://www.cnblogs.com/woxiaosade/p/13455567.html
Copyright © 2011-2022 走看看