转载

关于PECS原则

关于Java的泛型,我们经常使用<? super T>和<? extends T> 两种方式进行变量声明,这里面设计一个PECS的概念,如果理解不到位 可能会造成对集合进行set或get的时候编译报错,让你一头雾水。

概念

PECS的意思是 Producer Extends Consumer Super ,简单理解为如果是生产者则使用Extends这到底是啥意思呢?

下面的解释来自 StackOverflow ,很精辟:

tl;dr: “PECS” is from the collection’s point of view. If you are only pulling items from a generic collection, it is a producer and you should use extends; if you are only stuffing items in, it is a consumer and you should use super. If you do both with the same collection, you shouldn’t use either extends or super.

让我们通过一个典型的例子理解一下到底什么是Producer和Consumer:

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)); 
      }
  } 
}

上面的例子中将src中的数据复制到dest中,这里src就是生产者,它「生产」数据,dest是消费者,它「消费」数据。设计这样的方法,好处就是,可以复制任意类型的List,通用性特别强。

public class A {}

public class B extends A {}

public class C extends B {}

public void testCoVariance(List<? extends B> myBlist) {
    B b = new B();
    C c = new C();
    myBlist.add(b); // does not compile
    myBlist.add(c); // does not compile
    A a = myBlist.get(0);
}

public void testContraVariance(List<? super B> myBlist) {
    B b = new B();
    C c = new C();
    myBlist.add(b);
    myBlist.add(c);
    A a = myBlist.get(0); // does not compile
}

发现上面凡是 ? extends T 的集合,也就是Producer都不能「写」,凡是 ? super T 的集合,也就是Consumer都不能「读」。

有一个比较好记的方法:

A producer is allowed to produce something more specific, hence extends, a consumer is allowed to accept something more general, hence super.

References

  • What is PECS (Producer Extends Consumer Super)?

本文首次发布于S.L’s Blog, 作者 @stuartlau , 转载请保留原文链接.

  • Previous

    AOP的概念结合Spring的解析

原文  https://elsef.com/2020/04/06/关于PECS原则/
正文到此结束
Loading...