数组的协变性
如果类 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>(); |
为什么数组不支持范型?
假设数组支持范型,数组是在运行时才去判断数组元素的类型约束(此时范型信息已被擦除),因为无法做类型约束。