SoloCompany
2016-12-23 23:23:18 +08:00
generic / covariant / invariant
这几个概念建议都要看一下
早期的 java 没有泛型,但有数组,而数组在 java 语言里面是定义为 covariant 的,也就是赋值相容的,这其实是一个错误,因为把一个 String[] 类型转换为 Object[] 没有任何警告,但以后的元素赋值可能会产生 ClassCastException
Java 泛型的设计纠正了这个错误,是 invariant 的,也就是赋值不相容,你不能把 List<String> 直接当成 List<Object> 来用,但可以当做 List<? extends Object> 来用,自然而然, extends 和 super 关键字就是必须的了
invariant 的泛型也给编程带来很多麻烦,因为无法进行类型转换(当然,因为 java 的泛型是擦除的,强制转换并且消除警告也总是有办法做到的)
进一步的,如果你有看过 kotlin 的话,有专门章节介绍泛型, kotin 用 in / out 标记来代替了 extends / super , in / out 关键字不仅仅能修饰泛型参数类型,还能用来修饰泛型参数声明,配合不可变集合类型就能够支持 convariant 泛型(赋值相容)
比如 kotlin 的 List 是不可变的,其接口声明是 interface List<out E>;
意思是只能从里面取出来 E 类型的元素,不能保存
那么 List<String> 和 List<Object> 就变得赋值相容了