首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java PECS List<?超级T> dest和List<T> dest的区别?

java PECS List<?超级T> dest和List<T> dest的区别?
EN

Stack Overflow用户
提问于 2020-03-12 12:43:31
回答 2查看 66关注 0票数 1
代码语言:javascript
复制
public static <T> void copy1(List<? extends T> src, List<? super T> dest) {
    for (int i = 0; i < src.size(); i++) {
        dest.add(src.get(i));
    }
}

public static <T> void copy2(List<? extends T> src, List<T> dest) {
    for (int i = 0; i < src.size(); i++) {
        dest.add(src.get(i));
    }
}

top 2方法都能实现PECS效果,但有什么区别??

谢谢你!!

EN

回答 2

Stack Overflow用户

发布于 2020-03-12 13:31:17

PECS -> Producer扩展了消费者超级

  • ?从列表的角度扩展了T ->,它充当其他人的生产者。您可以从其中获取项(list produces),但不能向其中插入。在Java的世界里,它被称为协方差。
  • ?super T-->这被称为消费者行为,因为从列表的角度来看,它允许向其中添加项(列表消费),但在类型安全读取(生成)中没有用处。在这里是contravariance.
  • T -->,我们可以在列表中插入T类的任何子类型。当我们读取时,它将返回一种类型的T实例。这叫做不变性。

代码语言:javascript
复制
class  A{
    public int a;
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
}

class B extends A
{
    public int b;
    public int getB() {
        return b;
    }
    public void setB(int b) {
        this.b = b;
    }
}
public class GenericsDemo {

    public static void main(String[] args) {
        List<A> invariant = new ArrayList<>();
        List<? extends A> covariant = new ArrayList<>();
        List<? super A> contravariant = new ArrayList<>();

        invariant.add(new B());
        invariant.get(0).getA();
        //Error as it expect the instance of A while reading
        // invariant.get(0).getB();

        //Error it will be used to read the values, we can't insert any values in it.
        // We will use this construct places like defining params to a function
        //covariant.add(new B());
        //covariant.add(new A());

        contravariant.add(new A());
        contravariant.add(new B());

        //Error, it will be used to write only
        //While reading, it will give you object type
        //contravariant.get(0).getA();

        //We can type-cast while reading
        A a = (A) contravariant.get(0);
        a.getA();
 copy1(invariant,invariant);
        copy2(invariant,invariant);

       //Error due to the dest param requires super of T
       // copy1(covariant,covariant);
        //Error due to the dest param requires  of T
        //copy2(covariant,covariant);

        copy1(covariant,contravariant);
        copy2(covariant,contravariant);
    }
 public static <T> void copy1(List<? extends T> src, List<? super T> dest) {
        for (int i = 0; i < src.size(); i++) {
            dest.add(src.get(i));
        }
    }

    public static <T> void copy2(List<? extends T> src, List<T> dest) {
        for (int i = 0; i < src.size(); i++) {
            dest.add(src.get(i));
        }
    }

}

  • 方法1 -- > public static void copy1(List src,List dest) dest list将使用类型T及其子类的任何内容。但是,当我们读取它时,它将返回一个对象类型的实例,我们需要类型为caste。

代码语言:javascript
复制
- Methpd 2---> public static  void copy2(List src, List dest) dest list will consume anything with type T and it's sub class. But, when we read it, it will return the instance of T

参考--> https://medium.com/@isuru89/java-producer-extends-consumer-super-9fbb0e7dd268

PS:-很抱歉回答得太长了。

票数 1
EN

Stack Overflow用户

发布于 2020-03-12 13:48:08

在这个特定的示例中,两种方法都是相同的,因为类型T本身是无界的。因此,这两个声明都只是说明dst参数列表元素必须是src参数列表元素的超类,在copy1()中使用? super T并不会在这里添加任何新内容。

super规则并不意味着你必须总是把extends或PECS放在任何地方。下面是J.Bloch "Effective Java“的第32项中与PECS兼容的声明的完整示例:

代码语言:javascript
复制
public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2);

这里不需要使用返回类型作为Set<? super E>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60647745

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档