以下内容转自:

  原文链接: 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集合中去。

总结:

  1. 如果你是想遍历collection,并对每一项元素操作时,此时这个集合时生产者(生产元素),应该使用 Collection<? extends Thing>.
  2. 如果你是想添加元素到collection中去,那么此时集合时消费者(消费元素)应该使用Collection<? super Thing>

注:此文根据《Effective Java》以及Java Generics: What is PECS? 整理成文。想了解更多有关泛型相关知识,请读者阅读《Effective Java》的第五章。

[转]Java 泛型: 什么是PECS(Producer Extends, Consumer Super)的更多相关文章

  1. Java泛型 PECS(Producer Extends, Consumer Super)

    本文转载自ImportNew,原文链接 Java 泛型: 什么是PECS(Producer Extends, Consumer Super) PECS指“Producer Extends,Consum ...

  2. JAVA泛型知识(二)--> <? extends T>和<? super T>

    <? extends T> 和 <? super T> 是Java泛型中的“通配符(Wildcards)” 和 “边界(Bounds)”的概念 <? extends T& ...

  3. JAVA泛型中的有界类型(extends super)(转)

    JDK1.5中引入了泛型(Generic)机制.泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Ja ...

  4. Java 泛型中的PECS原则

    在泛型编程时,使用部分限定的形参时,<? super T>和<? extends T>的使用场景容易混淆,PECS原则可以帮助我们很好记住它们: 生产者(Producer)使用 ...

  5. Java泛型的定义以及对于<? extends T>和<? super T>

    Java 中对于泛型方法的定义: public <T> T getT(){ .....相关代码; } 其中我对<T>的理解就是申明只是一个泛型方法的标记,T是返回的类型. 对于 ...

  6. Java连接ActiveMQ代码示例(Producer和Consumer)

    import org.apache.activemq.ActiveMQConnection; import org.apache.activemq.ActiveMQConnectionFactory; ...

  7. 你对Java泛型的理解够深入吗?

    泛型 泛型提供了一种将集合类型传达给编译器的方法,一旦编译器知道了集合元素的类型,编译器就可以对其类型进行检查,做类型约束. 在没有泛型之前: /** * 迭代 Collection ,注意 Coll ...

  8. java泛型之通配符?

    一.在说泛型通配符" ?" 之前先讲几个概念 1.里氏替换原则(Liskov Substitution Principle, LSP): 定义:所有引用基类(父类)的地方必须能透明 ...

  9. 浅谈Java泛型中的extends和super关键字(转)

    通配符 在本文的前面的部分里已经说过了泛型类型的子类型的不相关性.但有些时候,我们希望能够像使用普通类型那样使用泛型类型: 向上造型一个泛型对象的引用 向下造型一个泛型对象的引用 向上造型一个泛型对象 ...

随机推荐

  1. EditPlus添加到右键菜单

    1.Alt+R 键打开“运行” 2.“运行”中输入:regedit 打开注册表    (1.在 "我的电脑HKEY_CLASSES_ROOT*" 下新建项 shell: (2.在 ...

  2. 复制选中的listbox内容

    private void lt_log_MouseClick(object sender, MouseEventArgs e) { Clipboard.SetDataObject(lt_log.Sel ...

  3. 不要温柔地走入promise

    第一步 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title ...

  4. C++ ASSERT() 断言机制

    C++ ASSERT() 断言机制 ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行.如果表达式不为0,则继 ...

  5. 如何删除github里面的文件夹?

    按照以下步骤即可(本地删除) 1. git pull you git url2. git checkout 3. rm -r dirName4. git add --all5. git commit  ...

  6. c How to Make an Ascii Picture.

    import java.io.*; public class trans{ public static void main(String[] args){ try{ File inFile = new ...

  7. web设计经验<二>设计华丽的用户体验的6个热门技巧

    你是否曾经下载了一个应用,却发现它“很难使用”?对于大多数智能手机用户来说,答案是肯定的. 有趣的是,每四个手机应用中就有一个应用在下载后被“打入冷宫”. 如果一个应用能够吸引一个人下载并且打开它,但 ...

  8. poj2826An Easy Problem?!

    链接 繁琐细节题. 1.线段无交点时,ans=0; 2.如图 假设过p3.y的水平线与p1p2相交 因为雨是垂直下落的,左图的情况是无法收集到雨水的,而这种情况有一种简便的判定方式 cross(p1- ...

  9. Android手机tcpdump抓包

    在开发过程中遇到问题时,无法非常方便的获取到数据包,导致分析解决问题比较麻烦.这里介绍如何在Android手机上实现tcpdump抓包.   1.root机器  在用tcpdump抓包过程中,需要使用 ...

  10. JAVA学习提高之----安装多个JDK版本的问题

    我的机器上最开始安装的是jdk1.6,后来因为工作需要又安装了jdk1.4.但是,环境变量我并未更改,还是指向jdk1.6的路径的.可是,在cmd窗口输入 Java -version 却得到是1.4. ...