由于 Java 泛型的擦除,经常会看到会给泛型加一个擦除的边界
<T extends X>
我想问的是:为什么不直接用多态来实现这种需求,这个擦除的边界不就相当于多态吗?
1
zhaohui318 2016-12-23 17:53:27 +08:00 1
|
2
misaka19000 2016-12-23 17:54:52 +08:00 via Android
@zhaohui318 很好,学习到了
|
3
fwrq41251 2016-12-23 18:56:20 +08:00 via Android
关键词:协变
|
4
incompatible 2016-12-23 19:06:44 +08:00
@zhaohui318 把 List<Dog>转换成一个 List<Animal>的最省事儿的方式:
public List<Animal> convert(List<Dog> dogList) { return (List) dogList; } |
5
21grams 2016-12-23 19:28:38 +08:00
这问题就相当于为什么用泛型不用多态
|
6
SoloCompany 2016-12-23 23:23:18 +08:00 4
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> 就变得赋值相容了 |
7
palmers 2016-12-24 07:55:21 +08:00 via iPhone
这个在 think in java 中有解释 泛型是 1.5 才加进来的 为了多方妥协最后采用擦出边界这么一个折中的办法
|