package list;
//在看容器源代码的时候 遇到了<? extends AnyClass> <? super AnyClass> 学习了一下 希望自己把学到的讲明白
// 首先 从数组讲起,声明一下 Fruit 水果类 Apple 苹果类 Banana 香蕉类 Banana Apple extends Fruit。Fruit[10] fruit=new Apple[10];
//Fruit[0]=new Fruit();Fruit[1]=new Apple();这俩行代码在编译期间是没有任何问题的。但是fruit指向的是
//Apple 数组,在运行时会出现异常。而我们使用泛型的主要目标之一就是把这种错误检查放到编译阶段。
//List<? extends Fruit> flist=new ArrayList<? extends Apple>();
//List<? extends Fruit> flist=new ArrayList<? extends Banana>();
//在这你可以想一下你可以从flist 里add什么?可以从flist 里get什么?
//其实你肯定可以读到 (get)Fruit,因为Fruit is Fruit Apple is Fruit,Banana is Fruit;
//你不能向其中插入任何类对象(的引用),因为你add(new Apple())时,flist可能的是List<Banana>,
//add(new(Banana())时,可能指得是List<Apple>...
//你不能往List<? extends T>中插入任何类型的对象,因为你不能保证列表实际指向的类型是什么,你并不能保证列
//表中实际存储什么类型的对象。唯一可以保证的是,你可以从中读取到T或者T的子类.
//现在 事情有点走向极端了,你甚至不能向一个刚刚申明过持有Apple 对象的List 存放Apple.但编译器并不知道这一点,
//List<? extendsFruit> 可以合法的指向一个 List<Banana>,但是一旦执行这种类型的向上转型,你不可以向其中传递
//任何对象。注意是任何。
//(这时 可以走另外一条路 逆变 也就是 超类型通配符 )即所谓的<?super AnyClass>
//List<? super Apple> fl=new ArrayList<Fruit>();
//List<? super Apple> fl=new ArrayList<Apple>();
//List<? super Apple> fl=new ArrayList<Object>();
//在这你可以想一下 你能add什么?get什么?
//其实你可以add Apple 的所有子类及 Apple,get 什么呢?不一定能读到Fruit,有可能是Object,不一定是Apple,有可能是Fruit;
//但是一定可以读到Object(不知道具体子类);
//PECS(原则)Produce Extends Consumer Super
//如果你需要一个列表提供T类型元素(即你想从列表中读取T类型的元素),你这样申明List<? extends T>;注意你不能add元素
//如果你需要一个列表使用T类型元素(即你想从列表中addT类型的元素),你这样申明List<? super T>;注意你不能保证读到的类型
//
//
public class LearnGeneric {
}
<? extends AnyClass> <? super AnyClass>
最新推荐文章于 2024-12-18 16:51:07 发布