泛型没有继承性
例子:List<Object> list = new ArrayList<String>();
会出现编译错误
边界和通配符?
规定泛型的上限
<? extends AA>
:支持 AA 或者 AA 子类
规定泛型的下限
<? super AA>
:支持 AA 类以及 AA 类的父类,不限于直接父类 比如Object顶级父类也支持
通配符?
<?>
任意的泛型类型都可以接受
Java泛型的型变
协变(Covariant)
协变是指在类型转换过程中,类型参数能够按照继承关系向上转型。具体地说,在使用泛型类或接口时,如果类型参数A是类型参数B的子类,则可以将泛型类型Foo<A>
视为Foo<B>
的子类型。
class Animal {}
class Dog extends Animal {}
class Foo<T> {}
Foo<Animal> foo1 = new Foo<Animal>();
Foo<Dog> foo2 = new Foo<Dog>();
// Foo<Dog> 是 Foo<Animal> 的子类型
Foo<Animal> foo3 = foo2;
在上述代码中,类 Dog
继承自类 Animal
,类 Foo 是一个泛型类。Foo<Animal>
和 Foo<Dog>
是不同的类型,但是由于 Dog
是 Animal
的子类,因此我们可以将 Foo<Dog>
赋值给 Foo<Animal>
,即 Foo<Dog>
是 Foo<Animal>
的子类型。
逆变(Contravariant)
逆变是指在类型转换过程中,类型参数能够按照继承关系向下转型。具体地说,在使用泛型类或接口时,如果类型参数A是类型参数B的超类,则可以将泛型类型Foo<B>
视为Foo<A>
的超类型。
class Animal {}
class Dog extends Animal {}
interface Bar<T> {}
class BarImpl<T> implements Bar<T> {}
Bar<Dog> bar1 = new BarImpl<Dog>();
Bar<Animal> bar2 = new BarImpl<Animal>();
// Bar<Animal> 是 Bar<Dog> 的超类型
Bar<Dog> bar3 = (Bar<Dog>) bar2;
在上述代码中,类 Dog
继承自类 Animal
,接口 Bar
是一个泛型接口,BarImpl
是实现了 Bar
接口的泛型类。Bar<Dog>
和 Bar<Animal>
是不同的类型,但是由于 Dog
是 Animal
的子类,因此我们可以将 Bar<Animal>
强制转换为 Bar<Dog>
,即 Bar<Animal>
是 Bar<Dog>
的超类型。
不变(Invariant)
不变是指在类型转换过程中,类型参数无法转换成其它类型参数。具体地说,在使用泛型类或接口时,如果类型参数A和类型参数B没有继承关系,那么泛型类型 Foo<A>
和 Foo<B>
是不兼容的。
List<Animal> animals = new ArrayList<>();
List<Cat> cats = new ArrayList<>();
animals = cats; //编译错误,List<Animal>和List<Cat>之间不存在子类型关系
综合案例
import java.util.ArrayList;
import java.util.List;
/**
* @author 安然的尾巴
* @version 1.0
*/
public class Test {
public static void main(String[] args){
//泛型没有继承性
//List<Object> list = new ArrayList<String>();
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<AA> list3 = new ArrayList<>();
List<BB> list4 = new ArrayList<>();
List<CC> list5 = new ArrayList<>();
}
// ? extends AA 表示 支持 AA 或者 AA 子类
//规定了泛型的上限
public static void print1(List<? extends AA> c) {
for (Object object : c) {
System.out.println(object);
}
}
//说明: List<?> 表示 任意的泛型类型都可以接受
public static void print2(List<?> c) {
for (Object object : c) { // 通配符,取出时,就是 Object
System.out.println(object);
}
}
// ? super 子类类名 AA:支持 AA 类以及 AA 类的父类,不限于直接父类 比如Object顶级父类也支持
//规定了泛型的下限
public static void print3(List<? super AA> c) {
for (Object object : c) {
System.out.println(object);
}
}
}
class AA{}
class BB extends AA{}
class CC extends BB{}