PECS法则
PECS 法则
: Producer Extends, Consumer Super
- 如果参数化类型表示一个生产者,就使用
上界通配符
<? extends T> - 如果它表示一个消费者,就使用
下界通配符
<? super T>
或者
- 如果你想从一个数据类型里获取数据(生产者),使用
上界通配符
<? extends T> - 如果你想把对象写入一个数据结构里(消费者),使用
下界通配符
<? super T>
或者
- 作为生产者提供数据(往外读取)时,适合用上界通配符(extends);
- 作为消费者消费数据(往里写入)时,适合用下界通配符(super)。
Collections.copy() 源码
/**
* @version JDK 1.8
* @param dest The destination list 消费者
* @param src The source list 生产者
*
* 数据流: src(生产者) -> desc(消费者)
* */
public class Collections {
// ...
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}
// ...
}
泛型擦除
private void query(List<String> params) {
// ...
}
private void query(List<Integer> params) {
// ...
}
List<String>
、List<Integer>
擦除后的类型为 List
反编译之后的方法代码如下
private void query(List params) {}
private void query(List<? extends String> params) {
// ...
}
private void query(List<? super Integer> params) {
// ...
}
List<? extends E>
、List<? super E>
擦除后的类型为 List<E>
反编译之后的方法代码如下
private void query(List<E> params) {}
参考
- 一文读懂Java泛型中的通配符 ?