26

我理解集合的get 和 put 原则:如果一个方法接受一个它将写入类型 T 的集合,则参数必须是Collection<? super T>,而如果它将从中读取类型 T ,则参数必须是Collection<? extends T>

但是有人可以解释一下Collections.max()签名吗:

public static <T> T max(Collection<? extends T> coll,
                    Comparator<? super T> comp)

特别是为什么它Comparator<? super T>而不是Comparator<? extends T>?

4

3 回答 3

66

Josh Bloch 的助记符PECS在这里很有用。它代表:

生产者extends,消费者super

这意味着当传递给方法的参数化类型将产生的实例T(它们将以某种方式从中检索)时,? extends T应该使用,因为子类的任何实例T也是T.

当传递给方法的参数化类型将使用的实例T(它们将被传递给它来做某事)时,? super T应该使用,因为T可以合法地将 的实例传递给任何接受某种超类型的方法T。例如, AComparator<Number>可以用在 a 上Collection<Integer>? extends T行不通,因为 aComparator<Integer>无法对 a 进行操作Collection<Number>

编辑: 澄清一下获取/放置(生产/消费):

public T something();
       ^

以上是一种产生T.

public void something(T t);
                      ^

上面是一个消耗T.

“生产者extends,消费者super”适用于传递参数化对象的方法将如何使用该对象。在 的情况下Collections.max(),将从 中检索项目Collection,因此它是生产者。这些项目将作为参数传递给 on 方法Comparator,因此它是一个消费者。

于 2010-02-11T23:13:14.993 回答
1

Comparator 消耗一对 T 并产生一个 int。集合产生比较器消耗的 Ts。

超级消费,延伸生产。

相对于 get 和 put 原则,get 生产和 put 消费。

于 2010-02-11T23:09:19.620 回答
0

比较器需要能够将 aT作为参数。

于 2010-02-11T22:51:11.847 回答