关于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.
本文首次发布于S.L’s Blog, 作者 @stuartlau , 转载请保留原文链接.
Previous
AOP的概念结合Spring的解析