zoukankan      html  css  js  c++  java
  • [转]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集合中去。

    总结:

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

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

  • 相关阅读:
    初心
    [CSP-S2019]:赛后总结
    最帅的快读
    检讨书模板
    $Linux$系统$GEDIT$编译运行$C++$和各种乱搞
    [CSP-S模拟测试]:C(倍增+数学)
    [CSP-S模拟测试]:B(期望DP)
    [CSP-S模拟测试]:A(单调栈维护凸包+二分答案)
    [NOIP2018]:旅行(数据加强版)(基环树+搜索+乱搞)
    [JZOJ6347]:ZYB玩字符串(DP+记忆化搜索)
  • 原文地址:https://www.cnblogs.com/GYoungBean/p/3552124.html
Copyright © 2011-2022 走看看