<? extends E>和<? super E>区别和使用
先看代码,在这类定义一下类的继承关系
class World { }
class Person extends World { }
class Teacher extends Person { }
一、<? extends E>,表示限定集合元素的上边界类型
比如下面集合:
ArrayList<? extends Person> list = new ArrayList<>();
list = new ArrayList<World>(); //编译错误
list = new ArrayList<Person>(); //编译通过
list = new ArrayList<Teacher>(); //编译通过
通过上面代码可以看到,<? extends E>限定了其集合里面的元素只能是Person类或者是其子类。
添加操作:不允许添加元素
list.add(new World()); //编译报错
list.add(new Person()); //编译报错
list.add(new Teacher()); //编译报错
此时list集合是不能添加元素的,因为? extends Person此时只是限定了list里面的元素是Person类型或者是继承与Person的类,并没有给定一个具体的类型。
读取操作:使用上边界限定的类型来接收
若list里面存在元素,可以取出list里面的元素,如下:
Person person = list.get(0);
因为此时,集合list的泛型只能是Person的类型或者是其子类,所用使用其上边界类来接收是可以的。
二、<? super E>,表示限定集合元素的下边界类型
比如下面集合:
ArrayList<? super Person> list = new ArrayList<>();
list = new ArrayList<World>(); //编译通过
list = new ArrayList<Person>(); //编译通过
list = new ArrayList<Teacher>(); //编译错误
通过上面代码可以看到,<? super E>限定了其集合里面的元素只能是Person类或者是其父类。
添加操作:允许添加Person类及其子类
list.add(new World()); //编译报错
list.add(new Person()); //编译通过
list.add(new Teacher()); //编译通过
此时list集合是允许添加Person类及其子类,因为? super Person此时只是限定了list里面的元素是Person类型或者是Person类的父类,当添加一个person的父类时候会失败,因为Person类的父类可能有很多,并不能确实其父类的类型,相反,添加Person类的子类是可以的,因为子类可以向上转型为父类类型。
读取操作:必须进行强制类型转换
若list里面存在元素,可以取出list里面的元素,如下:
World world = (World) list.get(0);
因为此时,集合list的泛型只能是Person的类型或者是父类,必须进行强转。
三、<? extends E>和<? super E>的使用
存取原则
根据? extends E 和 ? super E 通配符的特征,我们可以得出以下结论:
如果你想从一个数据类型里获取数据,使用 ? extends 通配符
如果你想把对象写入一个数据结构里,使用 ? super 通配符
如果你既想存,又想取,那就别用通配符。
PECS
PECS指“Producer Extends,Consumer Super”。
如果你是想遍历collection,并对每一项元素操作时,此时这个集合是生产者(生产元素),应该使用 Collection<? extends Thing>。
如果你是想添加元素到collection中去,那么此时集合是消费者(消费元素)应该使用Collection<? super Thing>。
》》》博主长期更新学习心得,推荐点赞关注!!!
》》》若有错误之处,请在评论区留言,谢谢!!!