Java中的通配符extends和super
extends
// Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Number>();
// Integer extends Number
List<? extends Number> foo3 = new ArrayList<Integer>();
// Double extends Number
List<? extends Number> foo3 = new ArrayList<Double>();
-
读操作(Reading)
给定以上的赋值语句,可以从foo3中读取什么类型的元素呢?
Number:Yes,因为foo3中的任何元素都可以保证是Number或Number的子类;
Integer: No,因为foo3有可能指向List<Double>;
Number: No,因为foo3有可能指向List<Integer>;
-
写操作(Wrting)
给定以上的赋值语句,可以向foo3中添加什么类型的元素呢?
Integer: No,因为foo3有可能指向List<Double>;
Number: No, 因为foo3有可能指向List<Integer>;
PECS(Producer Extends, Consumer Super)
如果你需要一个List作为Producer(希望从该List中读取T类型的元素),则需要声明该List为List<? extends T>,这时只能进行get操作,无法向List中add任何类型的元素;
如果你需要一个List作为Consumer(希望向该List中插入T类型的元素),则需要声明该List为List<? super T>,这时无法保证get到的元素的原有类型,只能得出是Object或Object的子类,只能add T或T的子类元素。
如果你即需要get、也需要add操作,则不能使用通配符,必须精确声明为List<T>。
举例:
jdk中Collections类的copy()方法: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()); } } }