有很长一段时间没弄明白,Java 中 <? super T> 与 <? extends T> 的区别,看过网上不少大神的解释,我的能力有限,好多都看到很迷糊,其中有一篇很浅显易懂,因此记下来,分享一下:java
<? extends T>是指:上界通配符(Upper Bounds Wildcards)spa
<? super T> 是指:下界通配符(Lower Bounds Wildcards)code
1. 概述:限定泛型只能为T类型的子类或者自己对象
2. 例子get
List<? extends Number> list2 = new ArrayList<Integer>(); List<? extends Number> list2 = new ArrayList<Double>(); List<? extends Number> list2 = new ArrayList<Number>();
3. 操做局限性源码
1. 概述:限定泛型只能为T类型的父类或者自己it
2. 例子io
List<? super Integer> list1 = new ArrayList<Integer>(); List<? super Integer> list1 = new ArrayList<Number>(); List<? super Integer> list1 = new ArrayList<Object>();
3. 操做局限性class
PESC原则泛型
生产者使用extends
若是你须要一个列表提供T类型的元素(即你想从列表中读取T类型的元素),你须要把这个列表声明成<? extends T>,好比List<? extends Integer>,所以你不能往该列表中添加任何元素。
消费者使用super
若是须要一个列表使用T类型的元素(即你想把T类型的元素加入到列表中),你须要把这个列表声明成<? super T>,好比List<? super Integer>,所以你不能保证从中读取到的元素的类型。
便是生产者,也是消费者
若是一个列表即要生产,又要消费,你不能使用泛型通配符声明列表,好比List<Integer>。
简单点来讲就是 使用时, 须要频繁的插入数据时, 就使用超类型限定, 须要获取数据时,就使用子类型限定
public static <T> void copy(List<? super T> destination, List<? extends T> source) { if (destination.size() < source.size()) { throw new IndexOutOfBoundsException("destination.size() < source.size(): " + destination.size() + " < " + source.size()); } Iterator<? extends T> srcIt = source.iterator(); ListIterator<? super T> destIt = destination.listIterator(); while (srcIt.hasNext()) { try { destIt.next(); } catch (NoSuchElementException e) { // TODO: AssertionError? throw new IndexOutOfBoundsException("Source size " + source.size() + " does not fit into destination"); } // 体现点 // ** srcIt.next()... // ** destIt.set()... destIt.set(srcIt.next()); } }