对 Java 之泛型通配符 ?extends T 的认知 和 ? super T 一些疑惑

2022-06-10 13:41:57 +08:00
 rqxiao
首先是 <? extends T>

可以是
List<? extends Fruit> flist =new ArrayList<Apple>();
也可以是
List<? extends Fruit> flist2 =new ArrayList<Banana>();

List<? extends Fruit> list 并不是说能添加 Fruit 子类的任意类型到 list 中。而是说<?extends Fruit>通配符实际上代表一种特定的类型,它只是表示 “某种特定的类型,但是 flist 没有指定“。就比如 flist2 里面声明的是 Banana 泛型,flist 声明的是 Apple 泛型 。
所以说 List<? extends Fruit> list 不能添加。因为其实从 List<? extends Fruit> 来看,这个集合会存什么样的 Fruit 子类它自己是未知的

但是 Apple a = (Apple)flist.get(0) 是可以的。在这个 List 中,不管它实际的类型到底是什么,但肯定能转型为 Fruit ,都是继承了 Fruit 的类,所以编译器允许返回 Fruit 。





其次是 ? super T 的疑惑

a5 继承了 a4 ,a4 继承了 a3 ,a3 继承了 a2. a2 继承了 a1
? super T 可以按照下面这么写
List<? super a5> a5List = new ArrayList<a5>();
List<? super a5> a4List = new ArrayList<a4>();
List<? super a5> a3List = new ArrayList<a3>();
List<? super a5> a2List = new ArrayList<a2>();
List<? super a5> a1List = new ArrayList<a1>();

我们可以知道向这些 List 添加一个 a5 或者其子类型的对象是安全的,这些对象都可以向上转型为 Apple 。

但是不能添加 a5 的父类。




不能添加 a5 的父类原因是这样吗?

List<? super a5> a3List ,里面实际存放的 都是 a3 类型。
a3List 不能添加 a2 的 ,因为 a2 类 并不能向下转成 a2 的子类 a3 ,
所以说 List<? super a5> 并不能添加 a5 的父类??
3423 次点击
所在节点    Java
22 条回复
NeroKamin
2022-06-13 16:59:00 +08:00
@GuuJiang 写的真通透,我在理解 PECS 的时候对于也有种怪怪的感觉,再看大佬写的一下子就明白了本质
mmdsun
2022-06-13 23:25:15 +08:00
@acidsweet 建议直接看 C sharp 的文档更全,kotlin 的逆变协变和关键字都是借鉴 C#,还有?空判断和扩展函数委托。设计思想几乎一模一样。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/858692

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX