JAVA PECS法则
2014-12-21 01:03
645 查看
什么是PECS?PECS指“Producer
Extends,Consumer Super”。换句话说,如果参数化类型表示一个生产者,就使用<? extends T>;如果它表示一个消费者,就使用<? super T>。
下面是一个简单的Stack的API接口:
假设想增加一个方法,按顺序将一系列元素全部放入Stack中,你可能想到的实现方式如下:
假设有个Stack<Number>,想要灵活的处理Integer,Long等Number的子类型的集合
此时代码编译无法通过,因为对于类型Number和Integer来说,虽然后者是Number的子类,但是对于任意Number集合(如 List<Number>)不是Integer集合(如List<Integer>)的超类,因为泛型是不可变的。
幸好java提供了一种叫有限通配符的参数化类型,pushAll参数替换为“E的某个子类型的Iterable接口”:
这样就可以正确编译了,这里的<? extends E>就是所谓的 producer-extends。这里的Iterable就是生产者,要使用<? extends E>。因为Iterable<? extends E>可以容纳任何E的子类。在执行操作时,可迭代对象的每个元素都可以当作是E来操作。
与之对应的是:假设有一个方法popAll()方法,从Stack集合中弹出每个元素,添加到指定集合中去。
假设有一个Stack<Number>和Collection<Object>对象:
同样上面这段代码也无法通过,解决的办法就是使用Collection<? super E>。这里的objects是消费者,因为是添加元素到objects集合中去。使用Collection<? super E>后,无论objects是什么类型的集合,满足一点的是他是E的超类,所以不管这个参数化类型具体是什么类型都能将E装进objects集合中
去。
总结:
1、如果你是想遍历collection,并对每一项元素操作时,此时这个集合时生产者(生产元素),应该使用 Collection<? extends Thing>
2、如果你是想添加元素到collection中去,那么此时集合时消费者(消费元素)应该使用Collection<? super Thing>
Extends,Consumer Super”。换句话说,如果参数化类型表示一个生产者,就使用<? extends T>;如果它表示一个消费者,就使用<? super T>。
下面是一个简单的Stack的API接口:
public class Stack<E>{ public Stack(); public void push(E e): public E pop(); public boolean isEmpty(); }
假设想增加一个方法,按顺序将一系列元素全部放入Stack中,你可能想到的实现方式如下:
public void pushAll(Iterable<E> src){ for(E e : src) push(e) }
假设有个Stack<Number>,想要灵活的处理Integer,Long等Number的子类型的集合
Stack<Number> numberStack = new Stack<Number>(); Iterable<Integer> integers = ....; numberStack.pushAll(integers);
此时代码编译无法通过,因为对于类型Number和Integer来说,虽然后者是Number的子类,但是对于任意Number集合(如 List<Number>)不是Integer集合(如List<Integer>)的超类,因为泛型是不可变的。
幸好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<E> dst){ if(!isEmpty()) dst.add(pop()); }
假设有一个Stack<Number>和Collection<Object>对象:
Stack<Number> numberStack = new Stack<Number>(); Collection<Object> objects = ...; numberStack.popAll(objects);
同样上面这段代码也无法通过,解决的办法就是使用Collection<? super E>。这里的objects是消费者,因为是添加元素到objects集合中去。使用Collection<? super E>后,无论objects是什么类型的集合,满足一点的是他是E的超类,所以不管这个参数化类型具体是什么类型都能将E装进objects集合中
去。
总结:
1、如果你是想遍历collection,并对每一项元素操作时,此时这个集合时生产者(生产元素),应该使用 Collection<? extends Thing>
2、如果你是想添加元素到collection中去,那么此时集合时消费者(消费元素)应该使用Collection<? super Thing>
相关文章推荐
- <Java/Hbase + C>云平台架构设计_十项法则 推荐
- Java泛型里的Get and Put法则
- JAVA笔记6__抽象类/接口/多态/instanceof关键字、父类设计法则
- 深入浅出 Java Concurrency (4): 原子操作 part 3 指令重排序与happens-before法则
- Java类型程序员每天提高工作效率的若干法则
- 各种 Java Thread State 第一分析法则
- Java 泛型: 什么是PECS(Producer Extends, Consumer Super)
- Java 泛型: 什么是PECS(Producer Extends, Consumer Super)
- 《编程导论(Java)·1.1.2 颠倒的世界(柏拉图法则)》
- 对于Java开发人员必须遵从的十大基本法则
- 各种 Java Thread State 第一分析法则
- java的23种设计模式法则(权威版)
- [科幻]Java版三体中黑暗森林法则的猜想
- Java开发者需要注意的十条法则
- 深入浅出 Java Concurrency (4): 原子操作 part 3 指令重排序与happens-before法则
- 各种 Java Thread State 第一分析法则
- <Java/Hbase + C>云平台架构设计_十项法则
- JAVA学习--面向对象思想的落地法则
- java 面向对象 OO 反射 "六原则一法则"
- 四则运算法则在Java中的实现