在阿里巴巴Java开发手册V1.4中,有一条强制规范是这样写的:

【强制】泛型通配符 <? extends T> 来接收返回的数据,此写法的泛型集合不能使用 add 方 法,
而<? super T>不能使用 get 方法,作为接口调用赋值时易出错。
说明:扩展说一下 PECS(Producer Extends Consumer Super)原则:
第一、频繁往外读取内容的,适合用<? extends T>。
第二、经常往里插入的,适合用<? super T>。

为何这样要求呢?
我们先来了解下 <? extends T><? super T>

<? extends T>

表示泛型类型必须是 T 或者T的子类.

举个例子: NumberIntegerLong 等类的父类

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

读取

显然,我们可以从 l 对象中读取到 Number 类型数据。
但是无法读取到具体是 Integer 或者 Long,因为可能读取到 Integer 也可能读取到 Long

写入

显然,我们不可能写入 Integer 类型数据到 List<? extends Number> l 中,因为 ? 可能是 Long. 同样的写入 Long 也是如此。
简单的可以理解为是不可写入的。

<? super T>

表示此类型是 T 或者T的父类.

举个上面的例子:

List<? super Integer> i = new ArrayList<Integer>();
List<? super Integer> i = new ArrayList<Number>();
List<? super Integer> i = new ArrayList<Object>();

读取

显然,我们不能从 i 对象中读取到 Integer 类型数据,因为可能是 Number 类型数据。同理,也不能读取到 Number 类型数据。
但是我们可以保证读取到的一定是 Object 类型数据(有个卵用)。
简单的可以理解为是不可读取的。

写入

可以写入 Integer 类型,或者 Integer 的父类 NumberObjecti 对象中。

PECS

生产者(Producer)使用extends,消费者(Consumer)使用super.

  1. 如果你需要 从列表读取 T 类型元素,则需要声明此列表为 List<? extends T>, 上面分析可知是不可写入的
  2. 如果你需要 写入 T 类型元素到列表,则需要声明此列表为 List<? super T>, 上面分析可知是不可读取的

关于这部分的讲解,参考中的2解释的很清楚,可以重点参考看下.

参考

  1. 泛型中? super T和? extends T的区别
  2. Java 之泛型通配符 ? extends T 与 ? super T 解惑