精华内容
参与话题
问答
  • 泛型PECS原则理解

    千次阅读 2018-10-12 20:14:45
    PECS即 Producer extends Consumer super 从集合中取元素, 使用<? extends T>通配符 向集合中放元素, 使用<? super T>通配符 问题 这里仍然使用网上常见的一个例子,...

    概念

    PECS即 Producer extends Consumer super
    即如果参数化类型表示一个T的生产者,使用<? extends T>,如果表示一个T的消费者,使用<? super T>。
    再通俗点说:

    • 从集合中取元素, 使用<? extends T>通配符
    • 向集合中放元素, 使用<? super T>通配符

    问题

    这里仍然使用网上常见的一个例子,Fruit、Apple、RedApple的例子
    继承关系为:

    RedApple extends Apple

    Apple extends Fruit

    首先明确一个问题:为什么会出现泛型通配符?

    Fruit fruit = new Apple();//没有问题 
    
    List<Fruit> list = new ArrayList<Apple>();//编译不通过 
    
    因为List<Fruit>不是List<Apple>的父类
    

    泛型中List的父类需要用List<? extends Apple>表示

    <? extends T>

    看一个例子:
    在这里插入图片描述
    从上面代码中可以看出,向fruitContainer中是不能添加元素的, 但是可以取出Fruit类型的元素

    可以这样理解:

    • 泛型就是一个标签,容器上贴上什么标签就只能放对应类别的东西,< Apple >:苹果容器,< Fruit >:水果容器,<? extends Fruit>:某种水果容器
    • 苹果容器(appleList)只能装苹果,不能装其它水果的,水果容器(fruitList)是可以装各种水果
    • 将一个水果容器(fruitList)贴上<? extends Fruit>标签以后,我们只知道它是放某种水果的容器,并不知道是放那种水果的容器,有可能是放苹果、也有可能是放香蕉的、还有可能是所有水果都能放的
    • 所以要对贴<? extends Fruit>标签的容器进行限制,不允许随意放入水果,假如是苹果容器,结果用户想放入香蕉呢,往外拿是可以的,因为我们知道拿出来的一定是Fruit

    <? super T>

    在这里插入图片描述

    • 代码中可以看出appleContainer是可以往里放元素的,放的元素只能是Apple以及其子类,取出的元素只能用Object接纳容器在贴上<? super T>标签后,我们只知道它是存放Apple或者是某种父类水果的容器
    • 放入水果时,只要是Apple以及子类都可以放心放入,但是Apple的父类就不能保证一定能放进去了,如果原来是Fruit容器还好,如果是Apple容器,当然不能放入Fruit啊,所以Apple的父类干脆都不让放
    • 取水果时从里面取出来的可能是Apple也可能是其父类,不能确定到底是什么所以只能用顶级父类Object存放
    展开全文
  • 台达PECS动力环境集中监控系统pdf,台达PECS动力环境集中监控系统
  • Java PECS

    2019-06-25 16:23:13
    extends The wildcard declaration ofList<? extends Number> foo3means that any of these are legal assignments: List<? extends Number> foo3 = new ArrayList<... // Number "e...

    extends

    The wildcard declaration of List<? extends Number> foo3 means that any of these are legal assignments:

    List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)
    List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
    List<? extends Number> foo3 = new ArrayList<Double>();  // Double extends Number
    1. Reading - Given the above possible assignments, what type of object are you guaranteed to read from List foo3:

      • You can read a Number because any of the lists that could be assigned to foo3 contain a Number or a subclass of Number.
      • You can't read an Integer because foo3 could be pointing at a List<Double>.
      • You can't read a Double because foo3 could be pointing at a List<Integer>.
    2. Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:

      • You can't add an Integer because foo3 could be pointing at a List<Double>.
      • You can't add a Double because foo3 could be pointing at a List<Integer>.
      • You can't add a Number because foo3 could be pointing at a List<Integer>.

    You can't add any object to List<? extends T> because you can't guarantee what kind of List it is really pointing to, so you can't guarantee that the object is allowed in that List. The only "guarantee" is that you can only read from it and you'll get a T or subclass of T.

    super

    Now consider List <? super T>.

    The wildcard declaration of List<? super Integer> foo3 means that any of these are legal assignments:

    List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
    List<? super Integer> foo3 = new ArrayList<Number>();   // Number is a superclass of Integer
    List<? super Integer> foo3 = new ArrayList<Object>();   // Object is a superclass of Integer
    1. Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from List foo3:

      • You aren't guaranteed an Integer because foo3 could be pointing at a List<Number>or List<Object>.
      • You aren't guaranteed a Number because foo3 could be pointing at a List<Object>.
      • The only guarantee is that you will get an instance of an Object or subclass of Object(but you don't know what subclass).
    2. Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:

      • You can add an Integer because an Integer is allowed in any of above lists.
      • You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists.
      • You can't add a Double because foo3 could be pointing at an ArrayList<Integer>.
      • You can't add a Number because foo3 could be pointing at an ArrayList<Integer>.
      • You can't add an Object because foo3 could be pointing at an ArrayList<Integer>.

    PECS

    Remember PECS"Producer Extends, Consumer Super".

    • "Producer Extends" - If you need a List to produce T values (you want to read Ts from the list), you need to declare it with ? extends T, e.g. List<? extends Integer>. But you cannot add to this list.

    • "Consumer Super" - If you need a List to consume T values (you want to write Ts into the list), you need to declare it with ? super T, e.g. List<? super Integer>. But there are no guarantees what type of object you may read from this list.

    • If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g. List<Integer>.

    Example

    Note this example from the Java Generics FAQ. Note how the source list src (the producing list) uses extends, and the destination list dest (the consuming list) uses super:

    public class Collections { 
      public static <T> void copy(List<? super T> dest, List<? extends T> src) {
          for (int i = 0; i < src.size(); i++) 
            dest.set(i, src.get(i)); 
      } 
    }

    Also see How can I add to List<? extends Number> data structures?

    From:https://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java

    展开全文
  • java 泛型 PECS准则

    2020-09-19 20:27:12
      我们知道<?>表示:我想使用Java泛型来编写代码,而不是用原生类型;但是在当前这种情况下,我并不能确定下泛型参数的... PECS: producer(读取)-extends, consumer(写入)-super。换句话说,如果输入参数表示一

      我们知道<?>表示:我想使用Java泛型来编写代码,而不是用原生类型;但是在当前这种情况下,我并不能确定下泛型参数的具体类型,因此用?表示任何某种类型。因此,根据我们对通配符的了解,使用无界通配符的泛型类不能够写数据,而在读取数据时,所赋值的引用也只能是 Object 类型。那么,我们究竟如何向泛型类写入、读取数据呢?

      《Effective Java2》给出了答案。 PECS: producer(读取)-extends, consumer(写入)-super。换句话说,如果输入参数表示一个 T 的生产者,就使用<? extends T>;如果输入参数表示一个 T 的消费者,就使用<? super T>。总之,通配符类型可以保证方法能够接受它们应该接受的参数,并拒绝那些应该拒绝的参数。 比如,一个简单的 Stack API :

    public class  Stack<E>{
        public Stack();
        public void push(E e);
        public E pop();
        public boolean isEmpty();
    }
    

      现在要实现pushAll(Iterable src)方法,将实现 Iterable 接口的 src 的元素逐一入栈:

    public void pushAll(Iterable<E> src){
        for(E e : src)
            push(e)
    }
    

      那么问题就来了:假设有一个实例化Stack的对象stack(类型参数被实例化为Number),显然, 我们向这个 stack 中加入Integer型或Float型元素都是可以的,因为这些元素本来就是Number型的。因此,src 就包括但不限于 Iterable与Iterable两种可能。这时,在调用上述pushAll方法时,编译器就会产生type mismatch错误。原因是显而易见的,因为Java中泛型是不变的,Iterable 与 Iterable 都不是 Iterable及其子类型中的一种。所以,我们对pushAll方法的设计就存在逻辑上的问题。因此,应改为

    // Wildcard type for parameter that serves as an E producer
    public void pushAll(Iterable<? extends E> src) {
        for (E e : src)
            push(e);
    }
    

      这样,我们就可以实现将实现Iterable接口的E类型的容器中的元素读取到我们的 Stack 中。


      那么,如果现在要实现popAll(Collection dst)方法,将 Stack 中的元素依次取出并添加到 dst 中,如果不用通配符实现:

    // popAll method without wildcard type - deficient!
    public void popAll(Collection<E> dst) {
        while (!isEmpty())
            dst.add(pop());   
    }
    

      同样地,假设有一个实例化Stack 的对象 stack , dst 为 Collection,显然,这是合理的。但如果我们调用上述的 popAll(Collection dst)方法,编译器会报出type mismatch错误,编译器不允许我们进行这样的操作。原因是显而易见的,因为Collection不是Collection及其子类型的一种。所以,我们对popAll方法的设计就存在逻辑上的问题。因此,应改为

    // Wildcard type for parameter that serves as an E consumer
    public void popAll(Collection<? super E> dst) {
        while (!isEmpty())
            dst.add(pop());
    }
    

      这样,我们就可以实现将Stack中的元素读取到我们的 Collection 中。在上述例子中,在调用 pushAll方法时,src生产了E实例(produces E instances);在调用popAll方法时 dst 消费了E实例(consumes E instances)。Naftalin与Wadler将PECS称为Get and Put Principle


      此外,我们再来学习一个例子:java.util.Collections的copy方法(JDK1.7),它的目的是将所有元素从一个列表(src)复制到另一个列表(dest)中。显然,在这里,src是生产者,它负责产生T类型的实例;dest是消费者,它负责消费T类型的实例。这完美地诠释了PECS:

    // List<? extends T> 类型的 src 囊括了所有 T类型及其子类型 的列表  
    // List<? super T> 类型的 dest 囊括了所有可以将 src中的元素添加进去的 List种类 
    public static <T> void copy(List<? super T> dest, List<? extends T> src) {
        // 将 src 复制到 dest 中
        int srcSize = src.size();
        if (srcSize > dest.size())
            throw new IndexOutOfBoundsException("Source does not fit in dest");
    
        if (srcSize < COPY_THRESHOLD ||
            (src instanceof RandomAccess && dest instanceof RandomAccess)) {
            for (int i=0; i<srcSize; i++)
                dest.set(i, src.get(i));
        } else {
            ListIterator<? super T> di=dest.listIterator();
            ListIterator<? extends T> si=src.listIterator();
            for (int i=0; i<srcSize; i++) {
                di.next();
                di.set(si.next());
            }
        }
    }
    

      因此,输入参数是生产者时,用 ? extends T;输入参数是消费者时,用 ? super T;输入参数既是生产者又是消费者时,那么通配符类型没什么用了:因为你需要的是严格类型匹配,这是不用任何通配符而得到的。无界通配符<?> 既不能做生产者(读出来的是Object),又不能做消费者(写不进去)。

    转自 https://blog.csdn.net/justloveyou_/article/details/52420071

    展开全文
  • JAVA PECS原则

    千次阅读 2018-05-29 21:19:17
    Java语言规范定义: jls7: 4.5.1: unlike ordinary type varables declared in a method signature, no type inference is required when using a wildcard. &lt;不同于普通的类型变量声明...
    Java语言规范定义:
        jls7: 4.5.1: unlike ordinary type varables declared in a method signature, no type inference is required  when using a wildcard.
        <不同于普通的类型变量声明,通配符方式并不会进行类型推断>说明:不进行类型推断的话实际上就限制了数据的放入和取出。    
        简而言之,需要明确的告诉编译器此数据的上界和下界,否则编译时报错。
        jls7:The null reference can always be assigned or cast to any reference type
        从上面的Java语言规范中可以得出:
            Java中所有类的顶级父类是Object,可以认为Null是所有类的子类。
    举个例子:
        <? extends T>:通配符?的类型在Null和T之间。 <? extends T>只能作为消费者,而不能放入类型的原因就在这里,编译器
    不能确定放入的是什么类型,Null可以转化为任意类型;换一种说法,编译器不知道类型的上界,只清楚类型的下界。如下图:


    <? super T>:通配符?的类型在T和Object之间。 <? super T>可以作为消费者也可以作为生产者的的原因就在这里,编译器
    很清楚放入的类型下界是T,上界是Object。如下图:


        <? extends T>和<? super T>在使用时,只能转化为其上界,相信大家已经明白了吧。
        PS:个人原创,欢迎转载
    展开全文
  • PECS原则

    千次阅读 2017-07-26 07:52:54
    经常发现有List、Set的声明,是什么意思呢?表示包括T在内的任何T的父类,表示包括T在内的任何T的子类,下面我们详细分析一下两种通配符具体的区别。 extends List foo3的通配符声明,意味着以下的赋值是合法的: ...
  • PECS(Producer Extends Consumer Super)原则

    千次阅读 2018-01-04 17:24:48
    参考 https://itimetraveler.github.io/2016/12/27/%E3%80%90Java%E3%80%91%E6%B3%9B%E5%9E%8B%E4%B8%AD%20extends%20%E5%92%8C%20super%20%E7%9A%84%E5%8C%BA%E5%88%AB%EF%BC%9F/   【Java】泛型中 extends 和...
  • Java泛型中的PECS原则

    万次阅读 2016-08-11 10:00:41
    参考:浅谈Java泛型中的extends和super关键字(转)Java泛型中的PECS原则Lists with wildcards cause Generic voodoo errorWhat is PECS (Producer Extends Consumer Super)?先来看一个错误:List&amp;amp;lt;? ...
  • PECS规则

    2018-09-20 10:59:55
    1.规则 集合中读取类型T的数据, ? extends T 或者 ? 集合中添加数据 ? super T ? 和 ? extends T不能添加数据 生产者使用“? extends T”通配符,消费者使用“? super T”通配符 2.示例 List&amp;lt;String&...
  • PECS原则:生产者(Producer)使用extends,消费者(Consumer)使用super。 1、生产者使用extends 如果你需要一个列表提供T类型的元素(即你想从列表中读取T类型的元素),你需要把这个列表声明成&lt;? ...
  • JAVA PECS法则

    千次阅读 2014-12-21 01:03:41
    什么是PECSPECS指“Producer Extends,Consumer Super”。换句话说,如果参数化类型表示一个生产者,就使用;如果它表示一个消费者,就使用。 下面是一个简单的Stack的API接口: public class StackE>{ public...
  • Java泛型之PECS原则

    2018-12-25 20:06:50
    文章目录上下界通配符的副作用上界&amp;amp;lt;? extends T&amp;amp;gt;不能往里存,只能往外取 ...上下界通配符的副作用 ...边界让Java不同泛型之间的转换更容易了。但不要忘记,这样的转换也有一定的副作用。...
  • PECS与泛型

    2018-08-24 17:48:44
    第一次看到PECS原则是在《阿里巴巴java开发手册》,看的我一头雾水。估计自己理解力太差了吧。。。。再次接触是在《阅读java编程思想》的时候。虽然这本书是基于jdk1.5编写的,有部分内容已不再适用现在新的jdk版本...
  • java泛型中的PECS

    2015-10-26 17:58:23
    extends List&lt;? extends Number&gt;   下面这三种通配符声明都是合法的 List&lt;? extends Number&gt; foo3 = new ArrayList&lt;Number&gt;(); // Number "......
  • 泛型通配符之PECS

    2019-05-21 00:08:01
    目录 基础知识点 上限通配符 List中上限通配符的add()方法 List中上限通配符的get()方法 下限通配符 ...List中下限通配符的add()方法 ... 在Java中,向上转型是允许的,但向下转型会无法编译通过。...
  • class Fruit {} class Apple extends Fruit {} class RedApple extends Apple {} 我们首先定义三个具有继承关系的class.... public class ArrayTest { public static void main(String[] args) { ...
  • 什么是PECS?  PECS指“Producer Extends,Consumer Super”。换句话说,如果参数化类型表示一个生产者,就使用;如果它表示一个消费者,就使用,可能你还不明白,不过没关系,接着往下看好了。 下面是一个简单的...
  • 前言:知人者智,自知者明;胜人者力,自胜者强。   ——《道德经》 一、概述 在 Java 中,其实所谓的泛型就是类型的参数化。如果方法有入参,那么这些入参面前往往会有类型,这个类型就是修饰参数所用。...

空空如也

1 2 3 4 5 ... 20
收藏数 1,704
精华内容 681
热门标签
关键字:

pecs