目录
前言
在上一篇博客中,我们认识了泛型,它会帮我们在编译器就拦截了类型转换异常。但是当泛型遇到继承呢?既然 Integer 继承自 Number,那 List<Integer> 是不是 List<Number> 的子类?
答案是否定的,接下来对这一知识点进行详细说明。
一、泛型的继承
泛型不具备继承性,但是数据具备继承性。

为什么Java不允许List<Animal> list = new ArrayList<Dog>()这样操作呢?
如果这行代码编译通过了,animalList表面是一个可以装所有动物的集合。那是不是说明一个继承自Animal类的Cat类也能存入animalList中。但是,animalList实际上是ArrayList<Dog>,等你想把它当狗拿出来的时候,程序就会崩溃。
数据具备继承性:
java
public class GenericsTest01 {
public static void main(String[] args) {
List<Animal> animalList = new ArrayList<>();
animalList.add(new Animal());
animalList.add(new Dog());
}
}
class Animal {}
class Dog extends Animal {}
二、泛型的通配符
现在有这样一个场景,需要定义一个方法,形参是一个集合,但是集合中的数据类型不确定,应该怎么做?
一般方法,使用泛型方法:
java
public class GenericsTest02 {
public static void main(String[] args) {
}
public static <E> void method(ArrayList<E> list){
}
}
存在缺陷,利用泛型方法此时它可以接收任意的数据类型:
java
public class GenericsTest02 {
public static void main(String[] args) {
ArrayList<Animal> al1 = new ArrayList<>();
ArrayList<Dog> al2 = new ArrayList<>();
ArrayList<Student> al3 = new ArrayList<>();
method(al1);
method(al2);
//这也是对的
method(al3);
}
public static <E> void method(ArrayList<E> list){
}
}
class Animal {}
class Dog extends Animal {}
class Student {}
但是我们通常希望,尽可能传递Animal类及其子类,此时就引出了泛型的通配符:
①上限限制:<? extends T>表示:泛型类型必须是 T 本身,或者是 T 的子类。
②下限限制:<? super T>表示:泛型类型必须是 T 本身,或者是 T 的父类。
此时上述修改后的方法为:

此时传递Student类时方法就会报错,但是传递Dog就不会。
泛型的通配符:可以限定类型的范围。
应用场景:
1.如果我们在定义类、方法、接口时,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。
2.如果类型不确定,但是能知道以后只能传递某个继承体系中的类,就可以使用泛型的通配符。
总结
-
泛型无继承:
List<Dog>不是List<Animal>。 -
<?>: 无界通配符,能接万物,但只能读不能写。 -
<? extends T>: 规定了上限。安全地读(取出 T)。 -
<? super T>: 规定了下限。安全地写(存入 T 的子类)。