[转]Java 泛型: 什么是PECS(Producer Extends, Consumer Super)
以下内容转自:
原文链接: stackoverflow 翻译: ImportNew.com- 刘志军
译文链接: http://www.importnew.com/8966.html
-----------------------------------------------------------------------
什么是PECS?
PECS指“Producer Extends,Consumer Super”。换句话说,如果参数化类型表示一个生产者,就使用<? extends T>;如果它表示一个消费者,就使用<? super T>,可能你还不明白,不过没关系,接着往下看好了。
下面是一个简单的Stack的API接口:
public class Stack<E>{
public Stack();
public void push(E e):
public E pop();
public boolean isEmpty();
}
假设想增加一个方法,按顺序将一系列元素全部放入Stack中,你可能想到的实现方式如下:
public void pushAll(Iterable<E> src){
for(E e : src)
push(e)
}
假设有个Stack<Number>,想要灵活的处理Integer,Long等Number的子类型的集合
Stack<Number> numberStack = new Stack<Number>();
Iterable<Integer> integers = ....;
numberStack.pushAll(integers);
此时代码编译无法通过,因为对于类型Number和Integer来说,虽然后者是Number的子类,但是对于任意Number集合(如List<Number>)不是Integer集合(如List<Integer>)的超类,因为泛型是不可变的。
幸好java提供了一种叫有限通配符的参数化类型,pushAll参数替换为“E的某个子类型的Iterable接口”:
public void pushAll(Iterable<? extends E> src){
for (E e: src)
push(e);
}
这样就可以正确编译了,这里的<? extends E>就是所谓的 producer-extends。这里的Iterable就是生产者,要使用<? extends E>。因为Iterable<? extends E>可以容纳任何E的子类。在执行操作时,可迭代对象的每个元素都可以当作是E来操作。
与之对应的是:假设有一个方法popAll()方法,从Stack集合中弹出每个元素,添加到指定集合中去。
public void popAll(Collection<E> dst){
if(!isEmpty()){
dst.add(pop());
}
}
假设有一个Stack<Number>和Collection<Object>对象:
Stack<Number> numberStack = new Stack<Number>();
Collection<Object> objects = ...;
numberStack.popAll(objects);
同样上面这段代码也无法通过,解决的办法就是使用Collection<? super E>。这里的objects是消费者,因为是添加元素到objects集合中去。使用Collection<? super E>后,无论objects是什么类型的集合,满足一点的是他是E的超类,所以不管这个参数化类型具体是什么类型都能将E装进objects集合中去。
总结:
- 如果你是想遍历collection,并对每一项元素操作时,此时这个集合时生产者(生产元素),应该使用 Collection<? extends Thing>.
- 如果你是想添加元素到collection中去,那么此时集合时消费者(消费元素)应该使用Collection<? super Thing>
注:此文根据《Effective Java》以及Java Generics: What is PECS? 整理成文。想了解更多有关泛型相关知识,请读者阅读《Effective Java》的第五章。
[转]Java 泛型: 什么是PECS(Producer Extends, Consumer Super)的更多相关文章
- Java泛型 PECS(Producer Extends, Consumer Super)
本文转载自ImportNew,原文链接 Java 泛型: 什么是PECS(Producer Extends, Consumer Super) PECS指“Producer Extends,Consum ...
- JAVA泛型知识(二)--> <? extends T>和<? super T>
<? extends T> 和 <? super T> 是Java泛型中的“通配符(Wildcards)” 和 “边界(Bounds)”的概念 <? extends T& ...
- JAVA泛型中的有界类型(extends super)(转)
JDK1.5中引入了泛型(Generic)机制.泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Ja ...
- Java 泛型中的PECS原则
在泛型编程时,使用部分限定的形参时,<? super T>和<? extends T>的使用场景容易混淆,PECS原则可以帮助我们很好记住它们: 生产者(Producer)使用 ...
- Java泛型的定义以及对于<? extends T>和<? super T>
Java 中对于泛型方法的定义: public <T> T getT(){ .....相关代码; } 其中我对<T>的理解就是申明只是一个泛型方法的标记,T是返回的类型. 对于 ...
- Java连接ActiveMQ代码示例(Producer和Consumer)
import org.apache.activemq.ActiveMQConnection; import org.apache.activemq.ActiveMQConnectionFactory; ...
- 你对Java泛型的理解够深入吗?
泛型 泛型提供了一种将集合类型传达给编译器的方法,一旦编译器知道了集合元素的类型,编译器就可以对其类型进行检查,做类型约束. 在没有泛型之前: /** * 迭代 Collection ,注意 Coll ...
- java泛型之通配符?
一.在说泛型通配符" ?" 之前先讲几个概念 1.里氏替换原则(Liskov Substitution Principle, LSP): 定义:所有引用基类(父类)的地方必须能透明 ...
- 浅谈Java泛型中的extends和super关键字(转)
通配符 在本文的前面的部分里已经说过了泛型类型的子类型的不相关性.但有些时候,我们希望能够像使用普通类型那样使用泛型类型: 向上造型一个泛型对象的引用 向下造型一个泛型对象的引用 向上造型一个泛型对象 ...
随机推荐
- Webbrowser控件判断网页加载完毕的简单方法 (转)
摘自:http://blog.csdn.net/cometnet/article/details/5261192 一般情况下,当ReadyState属性变成READYSTATE_COMPLETE时,W ...
- Codeforces Round #380 (Div. 2, Rated, Based on Technocup 2017 - Elimination Round 2) D. Sea Battle 模拟
D. Sea Battle time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- HttpServletResponse 学习
1: 利用Response向浏览器输出中文: private void test1(HttpServletResponse response) throws IOException { String ...
- SpringMVC后缀
<!-- 在这里,使用*.html为后缀的URL都能被baobaotao Servlet截获,进而转由SpringMVC框架进行处理.在 Struts框架中,一般将URL后缀配置为*.do:在w ...
- 基于Spark ALS构建商品推荐引擎
基于Spark ALS构建商品推荐引擎 一般来讲,推荐引擎试图对用户与某类物品之间的联系建模,其想法是预测人们可能喜好的物品并通过探索物品之间的联系来辅助这个过程,让用户能更快速.更准确的获得所需 ...
- linux学习笔记2-命令总结3
文件搜索命令 1.文件搜索命令 find 2.其他文件搜索命令 grep - 在文件中搜索字串匹配的行并输出 locate - 在文件资料库中查找文件 whereis - 搜索命令所在目录及帮助文档路 ...
- 什么是Plist文件
直接将数据直接写在代码里面,不是一种合理的做法.如果数据经常改,就要经常翻开对应的代码进行修改,造成代码扩展性低 因此,可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最新的数据.如果 ...
- intersection-of-two-arrays-ii
https://leetcode.com/problems/intersection-of-two-arrays-ii/ class Solution { public: vector<int& ...
- hostapd源代码分析(三):管理帧的收发和处理
hostapd源代码分析(三):管理帧的收发和处理 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004379 这篇文章我来讲解一下h ...
- centos 解压rar文件
默认情况下centos是不支持winrar的解压与打包的,需要安装winrar的linux版本程序 首先得下载解压软件 wget http://www.rarsoft.com/rar/rarlinux ...