定义几个基础类

// 动物类,一个吃方法
public static class Animal {

public void eat() {
System.out.println("Animal eat");
}
}

// 鸟继承自动物,一个飞方法
public static class Birds extends Animal {
public void fly() {
System.out.println("Birds fly");
}
}

// 孔雀继承自鸟,一个跳舞方法
public static class Peacock extends Birds {
public void dance() {
System.out.println("Peacock dance");
}
}
// 狗直接继承自动物,一个奔方法
public static class Dog extends Animal {
public void run() {
System.out.println("Dog run");
}
}

List<? super T>

当声明泛型使用的是​​super​​​,是规定了类型下界,即该数组元素的类型下限是​​T​​,后面定义装载的元素类型必须是​​T​​​本身或者​​T​​的父类。

例如下面这行代码

List<? super Animal> listSuper = new ArrayList<>();

1、​​new ArrayList<>()​​​后面的​​<>​​​只能是​​Animal​​​本身或者它的父类比如​​Object​​,不填默认就是其本身

错误示例​​Birds​​​不是​​Animal​​​本身或父类
List<? extends T>和List<? super T>之间的区别_java
正确示例
List<? extends T>和List<? super T>之间的区别_子类_02
List<? extends T>和List<? super T>之间的区别_面试_03
List<? extends T>和List<? super T>之间的区别_后端_04

2、而​​listSuper​​​能添加的元素范围只能是​​super T​​​中​​T​​​本身或者​​T​​的子类

示例1:​​T​​​为​​Animal​​​,所以子类以及本身都能被添加
List<? extends T>和List<? super T>之间的区别_后端_05
示例2:​​​T​​​为​​Animal​​​,所以子类以及本身都能被添加List<? extends T>和List<? super T>之间的区别_后端_06
示例3:​​​T​​​为​​Birds​​​,所以子类以及本身都能被添加,而父类和其他类不行List<? extends T>和List<? super T>之间的区别_后端_07

List<? extends T>

是被设计用来读取数据的泛型,并且只能读取类型为T的元素
当声明泛型使用的是​​​extends​​​,是规定了类型上界,即该数组元素的类型上限是​​T​​,后面定义装载的元素类型必须是​​T​​​本身或者​​T​​的子类。

例如下面这行代码

List<? extends Animal> listExtends= new ArrayList<>();

1、​​new ArrayList<>()​​​后面的​​<>​​​只能是​​Animal​​​本身或者它的子类比如​​Birds​​​,不填默认就是其本身
List<? extends T>和List<? super T>之间的区别_父类_08
2、​​​listExtends​​​只能读取,不能插入任何有意义的元素,但可以插入​​null​​​List<? extends T>和List<? super T>之间的区别_子类_09
这是因为,你不知道里面的元素具体是什么类型,当你add(​​new Birds()​​),它真实的类型有可能是​​Peacock​​,而​​List<Peacock>​​是不能添加​​new Birds()​​的

那为什么​​super​​就可以呢?因为定义的是父类,父类可以添加子类,不管是​​Dog、Birds、Peacock​​还是​​Animal​​都可以添加进​​List<Animal>​

3、​​listExtends​​​里面的元素取​​T​​​本身不需要强制转换类型,但子类需要
List<? extends T>和List<? super T>之间的区别_面试_10
上文提到,你不能知道具体添加的是什么,但你能确定的是,取出来的都是​​​T​​​或​​T​​的子类

总结​​super​​​的​​<>​​里面是自身或父类,内部元素是自身或子类

相反​​extends​​​的​​<>​​里面是自身或子类,只读

所以
**extends 可用于的返回类型限定,不能用于参数类型限定。

super 可用于参数类型限定,不能用于返回类型限定**

参考stackoom文章:​​之间的区别 <? super T> 和 <? extends T> 在Java中[重复]​