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

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>。

Java泛型 PECS(Producer Extends, Consumer Super)的更多相关文章

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

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

  2. [转]Java 泛型: 什么是PECS(Producer Extends, Consumer Super)

    以下内容转自: 原文链接: stackoverflow 翻译: ImportNew.com- 刘志军 译文链接: http://www.importnew.com/8966.html -------- ...

  3. 浅谈Java泛型中的extends和super关键字

    泛型是在Java 1.5中被加入了,这里不讨论泛型的细节问题,这个在Thinking in Java第四版中讲的非常清楚,这里要讲的是super和extends关键字,以及在使用这两个关键字的时候为什 ...

  4. Java泛型(6):extends和super关键字

    (1) <T extends A> 因为擦除移除了类型信息,而无界的泛型参数调用的方法只等同于Object.但是我们可以限定这个泛型参数为某个类型A的子集,这样泛型参数声明的引用就可以用类 ...

  5. Java泛型 通配符? extends与super

    Java 泛型 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 <? super T> 表示类型下界(Java ...

  6. Java泛型中的extends和super关键字

    理解List<? extends T> list, T key, Comparator<? super T> c 这些一般用在方法形参类型上,用于接受泛型对象. 1.List& ...

  7. Java泛型中<? extends E>和<? super E>的区别

    这篇文章谈一谈Java泛型声明<? extends E>和<? super E>的作用和区别 <? extends E> <? extends E> 是 ...

  8. 如何理解 Java 中的 <T extends Comparable<? super T>>

    Java 中类似 <T extends Comparable<? super T>> 这样的类型参数 (Type Parameter) 在 JDK 中或工具类方法中经常能看到. ...

  9. Java泛型中<?> 和 <? extends Object>的异同分析

    相信很多人和我一样,接触Java多年,却仍旧搞不清楚 Java 泛型中 <?>和 <? extends Object>的相似和不同.但是,这应该是一个比较高端大气上档次的Que ...

随机推荐

  1. 粘性页脚 Sticky Footer 最佳方式

    前段时间工作中遇到粘性页脚的需求,以前用过JS控制过,最后发现flex布局是解决这类问题的好帮手. 粘性页脚:即使没有足够的内容填充页面,也要将页脚固定到窗口的底部. <!DOCTYPE htm ...

  2. java工厂模式个人体会

    上一边文章主要对单例模式做了一个总结,这篇文章主要对工厂模式也写一写个人的体会. 工厂模式是设计模式的一种,它主要是把实现产品对象的过程封装起来,然后提供给客户端相应的接口.工厂模式也是有3种,分别为 ...

  3. JQuery实现获取多个input输入框的值,并存放在一个数组中

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. javascript函数中with的介绍

    /*js函数中with函数的用法分析定义 方便用来引用某个对象中已有的属性但是不能用来给对象添加属性 要给对象创建新的属性 必须明确的引用该对象*/代码格式with(object) statement ...

  5. Maven学习总结(四):更改maven的编码格式方式

    安装系统之后,一般中文系统默认字符集是GBK.我们安装的软件一般都继承使用操作系统的默认字符集.所以当在中文XP或者win7系统开发,在使用maven(mvn compile)编译项目的时候,就会出现 ...

  6. 转:在使用angularjs过程,ng-repeat中track by的作用

    转载:链接 <div ng-repeat="links in slides"> <div ng-repeat="link in links track ...

  7. How to save rules of the iptables?

    The easy way is to use iptables-persistent. Install iptables-persistent: sudo apt-get install iptabl ...

  8. 单选按钮(RadioButton)

    一:RadioButton的相关属性: 1.Activity //单选按钮 public class RadioButtonActivity extends Activity { private Co ...

  9. IOS地理信息使用

    概览 现在很多社交.电商.团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用和导航应用所特有的.的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式.例如你到了一个 ...

  10. restful知识点之六rest-framework组件流程图