您的位置:首页 > 编程语言 > Java开发

Java 泛型 PECS

2016-10-27 00:00 155 查看
最近在研究框架的源码,发现有好多代码中使用了很多泛型了的用法<? extends>和<? super>。以前看《Java编程思想》的时候也有所了解,但是具体不是很清楚,所以写了这篇博客分享一下。其实这写用法可以叫做Java泛型PECS法则。

一、什么是PECS:

PECS指“Producer Extends Consumer Super”如果参数化类型表示一个生产者就使用<? extends T>,
如果它表示一个消费者就使用<? super T>。

下面举例说明:

1. 生产者:
有一个List<Producer> producerList, 如果我们只从这个producerList中读取数据,而不从中添加数据,那这个List就称为Producer,即生产者。

2.消费者:
如果我们只向一个List<Consumer> consumer中添加数据,则这样的List就被称为Consumer,即消费者。

二、PECS的用法:

1.生产者的用法:
定义numList:

List<? extends Number> numList = new ArrayList<Number>();

<? extends Number>表示最高父类是Number类型,Integer, Double都属于Number的子类,所以在实例化List<? extends Number>这样的List时,可以传入任意Number类型的子类以及它自己,进行实例化。
1. <? extends Number>的最高父类是Number类型。所以从List<? extends Number>中拿出的数据可以保证是Number类型。
2. 假设List<? extends Number>中可以放Number、Double、Interger三种类型,当我们从List中取出数据时是不能确定具体是哪一种类型。所以List<? extends Number>是不能做添加操作的,Java是不允许这样的操作的。

###### 2.消费者用法:
定义numList
```
List<? super Integer> intList = new ArrayList<Integer>();
```
<? super Integer>表示最小子类是Integer,super代表了?可以是任意一种Integer的父类类型。所以可以向其添加任意Integer父类类型。但是Java是拒绝读取操作的。

###### 3.总结:
1) 参数写成:T<? super B>,对于这个泛型,?代表容器里的元素类型,由于只规定了元素必须是B的超类,导致元素没有明确统一的“根”(除了Object),所以这个泛型你其实无法使用它(除了把元素强制转成Object)。所以只能插入操作,而无法读

2) 参数写成: T<? extends B>,由于指定了所有元素的“根”是B,你任何时候都可以安全的用B来使用容器里的元素,但是插入有问题,由于以B为祖先的子树有很多,不同子树不兼容,所以禁止做插入操作,只做读取

[参考1](http://dz.sdut.edu.cn/blog/subaochen/2017/01/generics-pecs/)

[参考2](http://www.importnew.com/17006.html)

[参考3](http://www.cnblogs.com/lucky_dai/p/5485421.html)

[参考4](http://www.ciaoshen.com/2016/08/21/superExtends/)

[参考5](http://leekai.me/java-extends-super//)

[参考6](https://www.zhihu.com/question/20400700/answer/117464182)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: