约书亚布洛赫想出了佩奇,它说规则时使用?扩展T和?超级T.如果你想在佩奇集合框架方面,那么它是非常简单的。如果添加值的数据结构,使用?超级T.如果从数据结构中读取,使用?扩展T.例如:
public class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}
如果我检查的签名
public static <T> void sort(List<T> list, Comparator<? super T> c)
我看到的比较器使用?超好,所以它应该是消费者。看代码,比较C仅使用,因为它被要求比较的逻辑产生的东西。
一方面,我明白为什么它是一个超级因为作为一个开发者,我想用T级的比较器和比较器也超级T级的,因为T的对象的类型为超类T的也不过当我尝试去思考佩奇而言,我不明白。
难道只有佩奇持有集合框架?如果没有,就有人向我解释什么比较的Collections.sort消费?
对于这个答案的缘故,让我们Comparator
为主体,指导例子。
如果你仔细想想,你会看到Comparator
实际收到类型T
的两个参数,并返回它们的比较(由int
表示)的结果。换句话说,它消耗型T
的两个实例,并产生int
值。所以,作为由PECS规则,它是一个消费T
的,因此,使用? super T
的。
更一般地,你应该看的主要类型的相对于它的类型泛型参数中的每一个点考虑生产者和消费者。如果某些Comparator
型消费型T
的对象时,佩奇规则规定,这种Comparator<T>
的用户可以用它来比较的对象,其类型为T
的亚型。
作为一个具体的例子,如果你碰巧已经有了比较两个通用Number
实例(无论其具体类型实际上是)的逻辑,你可以使用它即比较Double
情况下,因为双打的数字,毕竟。
请看下面的比较:
Comparator<Number> c = Comparator.comparingInt(Number::intValue);
这里,比较器c
通过仅考虑它们的组成部分相比较Number
实例(任何数量)。
如果你有Double
实例如下列表:
List<Double> doubles = Arrays.asList(2.2, 2.1, 7.3, 0.2, 8.4, 9.5, 3.8);
而下面的sort
方法:
static <T> void sort(List<T> list, Comparator<T> c) {
list.sort(c);
}
(注意在? super T
参数不存在通配符Comparator
的)。
然后,如果要排序的List<Double> doubles
名单,上面sort
方法的签名会要求你通过一个具体的Comparator<Double>
。但是,如果你想使用先前定义的c
比较排序的List<Double> doubles
什么?
作为比较的类型是Comparator<Number>
,并作为doubles
列表的类型是List<Double>
,下面的代码会产生一个编译错误:
sort(doubles, c);
幸运的是,Comparator
是比较元素类型的消费者,你可以改变sort
方法的签名:
static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
而现在,这样的代码将编译:
sort(doubles, c);