定义几个基础类
// 动物类,一个吃方法
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
本身或父类
正确示例
2、而listSuper
能添加的元素范围只能是super T
中T
本身或者T
的子类
示例1:T
为Animal
,所以子类以及本身都能被添加
示例2:T
为Animal
,所以子类以及本身都能被添加
示例3:T
为Birds
,所以子类以及本身都能被添加,而父类和其他类不行
List<? extends T>
是被设计用来读取数据的泛型,并且只能读取类型为T的元素
当声明泛型使用的是extends
,是规定了类型上界,即该数组元素的类型上限是T
,后面定义装载的元素类型必须是T
本身或者T
的子类。
例如下面这行代码
List<? extends Animal> listExtends= new ArrayList<>();
1、new ArrayList<>()
后面的<>
只能是Animal
本身或者它的子类比如Birds
,不填默认就是其本身
2、listExtends
只能读取,不能插入任何有意义的元素,但可以插入null
这是因为,你不知道里面的元素具体是什么类型,当你add(new Birds()
),它真实的类型有可能是Peacock
,而List<Peacock>
是不能添加new Birds()
的
那为什么super
就可以呢?因为定义的是父类,父类可以添加子类,不管是Dog、Birds、Peacock
还是Animal
都可以添加进List<Animal>
3、listExtends
里面的元素取T
本身不需要强制转换类型,但子类需要
上文提到,你不能知道具体添加的是什么,但你能确定的是,取出来的都是T
或T
的子类
总结super
的<>
里面是自身或父类,内部元素是自身或子类
相反extends
的<>
里面是自身或子类,只读
所以
**extends 可用于的返回类型限定,不能用于参数类型限定。
super 可用于参数类型限定,不能用于返回类型限定**
参考stackoom文章:之间的区别 <? super T> 和 <? extends T> 在Java中[重复]