? extends E 和 ? super E 区别和使用

<? extends E>和<? super E>区别和使用

先看代码,在这类定义一下类的继承关系

class World { }

class Person extends World { }

class Teacher extends Person { }

一、<? extends E>,表示限定集合元素的上边界类型

比如下面集合:

ArrayList list = new ArrayList<>();
list = new ArrayList(); //编译错误
list = new ArrayList(); //编译通过
list = new ArrayList(); //编译通过

通过上面代码可以看到,<? 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 list = new ArrayList<>();
list = new ArrayList(); //编译通过
list = new ArrayList(); //编译通过
list = new ArrayList(); //编译错误

通过上面代码可以看到,<? 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
如果你是想添加元素到collection中去,那么此时集合是消费者(消费元素)应该使用Collection

》》》博主长期更新学习心得,推荐点赞关注!!!
》》》若有错误之处,请在评论区留言,谢谢!!!

你可能感兴趣的:(java)