数组的协变性
如果类 Base
是类 Derived
的父类,那么 Base[]
就是 Derived[]
的父类。
因此,我们的代码可以这么写:
1 | Number[] array1 = new Number[2]; |
但是,数组的协变性可能会导致一些难以发现的错误,比如下面的代码:
1 | /* Error A */ |
Error A
可以通过编译,Object[]
类型的引用(注意左边是引用)可以指向一个 String[]
类型的对象。但是,这在运行的时候会报错:
1 | Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer |
1 | /* Error B */ |
Error B
这种错误可以在编译的时候出现。
范型类不具有协变性
最后,范型类 不具有协变性
,如 List<Base>
不会是 List<Derived>
的父类。
1 | List<Object> list = new ArrayList<String>(); // 在这里直接凉了 |
为什么范型是不协变的?
因为这样做会破坏要提供的类型的安全范型。如果能够将 List<Integer>
赋值给 List<Number>
,那么下面的代码将允许将非 Integer
的内容放入 List<Integer>
。
1 | List<Integer> intList = new ArrayList<Integer>(); |
numList
实际上引用的是一个 List<Integer>
,只能存 Integer
或者其 子类
,所以在第二行就禁止了这种赋值行为。List<Integer>
和 List<Number>
两者是不同的类,且没有继承关系。
如果需要这样的赋值,比如作为函数的参数,可以这么做:
1 | List<Integer> intList = new ArrayList<Integer>(); |
为什么数组不支持范型?
假设数组支持范型,数组是在运行时才去判断数组元素的类型约束(此时范型信息已被擦除),因为无法做类型约束。