PE,CS全称是producer extends,consumer super的缩写,这是 Joshua Bloch 在 Effective Java 一书 中引入的一个略显奇怪的术语,但有助于理解泛型的用法。换言之,参数化类型表明 生产者(producer)则使用 extends, 表明消费者(consumer)则使用 superjava
简单来讲, PE 表示,若是你的方法只是想从集合获取值,而且但愿集合的类型范围是T及其子类,那么泛型能够定义为
? extends T
app
了解泛型的同窗应该知道 extends
是上界通配符,使用了上界通配符,只能读取值,不能写入值,取值的的类型是Tui
只能取值不能写入的就是生产者,有人可能有点理解了,咱们来个更详细的解释,举个栗子this
假设,咱们有个水果的对象,水果类有个addAll
方法,用来将另外一个水果集合,放入到水果对象内code
class Fruit{ private List<Fruit> fruits = new LinkedList<>(); public void addAll(List<Fruit> fruits){ for (Fruit fruit : fruits) { this.fruits.add(fruit); } } }
如今,咱们需求变了,有苹果,香蕉分别继承了水果这个类,若是我么将苹果或者香蕉集合直接放入addAll
方法,会编译报错,由于苹果集合,不是水果集合对象
public static void main(String[] args){ List<Apple> appleList = new LinkedList<>(); Fruit fruit = new Fruit(); // 编译报错 fruit.addAll(appleList); } class Apple extends Fruit{ } class Banana extends Fruit{ }
若是咱们要放进去怎么办,使用上界通配符,修改addAll
方法,使用了上界通配符后,元素只能读,不能写,传入的集合类型范围是Fruit或者其子类集合继承
public void addAll(List<? extends Fruit> f){ for (Fruit fruit : f) { this.fruits.add(fruit); }
有人会问了,这个上界通配符,跟PE有什么关系? 固然有,PE是producer extends
的缩写,咱们仔细看看,对于addAll
方法来讲,只是要消费入参,那么入参就是生产者,说着这,估计不少人已经明白了it
PE是针对方法来讲的,若是某个方法的入参,须要一个生产者,而且范围是泛型的子类,那么使用上界通配符extends编译
简单来讲, CS 表示,若是你的方法只是想往集合写入值,而且集合的类型范围但愿是T及其父类,那么泛型能够定义为
? super T
来表示class
了解泛型的同窗应该知道,super
表示下界通配符,使用了下界通配符,只能写入值,不能取值,写入的值必须是T或者其子类
只能写入,不能取出就是消费者,有人可能有点理解了,咱们来个更详细的解释,举个例子
咱们仍是沿用上面的例子,咱们进行改造一下,苹果类有个addAll
方法,传入一个苹果集合,将苹果对象放入这个集合里面
public class Apple extends Fruit{ private Apple apple = new Apple(); public void addAll(List<Apple> apples){ apples.add(apple); } }
如今需求变了,咱们变动,咱们想传入一个更大的水果集合,将苹果添加入水果集合里面,毕竟苹果是属于水果的子类,咱们直接将水果集合传入进去,会编译报错,咱们改造一下addAll
方法,使用下界通配符将它的接收范围扩大,传入的集合范围是Apple或者其父类集合
public void addAll(List<? super Apple> apples){ apples.add(apple); }
有人会问了,这个下界通配符,跟CS有什么关系? 固然有,CS是consumer super
的缩写,对于addAll
方法来讲,只要是将东西放进到入参内,那么入参就是消费者
CS也是针对方法来讲的,若是某个方法的入参须要消费方法内的东西,入参而且是泛型的父类,那么使用下界通配符super
若是进行简单的概括,那就是