java pecs_Java 泛型: 什么是PECS(Producer Extends, Consumer Super)

本文介绍了PECS原则,即Producer Extends(生产者扩展)和Consumer Super(消费者超类)的概念,通过实例展示了如何在Java中利用有限通配符解决泛型类型限制,以适应不同场景下的栈和集合操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是PECS?

PECS指“Producer Extends,Consumer Super”。换句话说,如果参数化类型表示一个生产者,就使用;如果它表示一个消费者,就使用,可能你还不明白,不过没关系,接着往下看好了。

下面是一个简单的Stack的API接口:

public class Stack{

public Stack();

public void push(E e):

public E pop();

public boolean isEmpty();

}

假设想增加一个方法,按顺序将一系列元素全部放入Stack中,你可能想到的实现方式如下:

public void pushAll(Iterable src){

for(E e : src)

push(e)

}

假设有个Stack,想要灵活的处理Integer,Long等Number的子类型的集合

Stack numberStack = new Stack();

Iterable integers = ....;

numberStack.pushAll(integers);

此时代码编译无法通过,因为对于类型Number和Integer来说,虽然后者是Number的子类,但是对于任意Number集合(如List)不是Integer集合(如List)的超类,因为泛型是不可变的。

幸好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 dst){

if(!isEmpty()){

dst.add(pop());

}

}

假设有一个Stack和Collection对象:

Stack numberStack = new Stack();

Collection objects = ...;

numberStack.popAll(objects);

同样上面这段代码也无法通过,解决的办法就是使用Collection super E>。这里的objects是消费者,因为是添加元素到objects集合中去。使用Collection super E>后,无论objects是什么类型的集合,满足一点的是他是E的超类,所以不管这个参数化类型具体是什么类型都能将E装进objects集合中去。

总结:

如果你是想遍历collection,并对每一项元素操作时,此时这个集合时生产者(生产元素),应该使用 Collection extends Thing>.

如果你是想添加元素到collection中去,那么此时集合时消费者(消费元素)应该使用Collection super Thing>.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值