2010-02-11 40 views
25

我明白收集的get and put principle:如果一个方法需要一个集合,它将写入一个类型T to,参数必须是Collection<? super T>,而如果它会读取键入T,参数必须是Collection<? extends T>Java的泛型:Collections.max()签名和比较器

但可能有人请解释Collections.max()签名:

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

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

回答

65

乔希布洛赫的助记符佩奇在这里很有用。它代表:

生产者extends,消费者super

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

当一个参数化类型被传递给方法消耗T实例(它们将被传递给它做的东西),? super T应该使用,因为T一个实例可以合法地传递给一个接受任何方法一些超类型的T。例如,Comparator<Number>可以在Collection<Integer>上使用。 ? extends T将不起作用,因为Comparator<Integer>无法在Collection<Number>上运行。

编辑: 为了澄清多一点上获取/放置(生成/使用):

public T something(); 
    ^

以上是产生T的方法。

public void something(T t); 
        ^

以上是消耗T的方法。

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

0

比较器需要能够采取T作为参数。

+0

我想也许我不完全理解get/put原则然后...? – 2010-02-11 23:09:08

+6

我推荐阅读那些讨论“PECS”的Effective Java章节。 想想这样:如果我要求你对一个双精选列表进行排序,并给你一个Comparator 来做这件事,你会怎么看? – 2010-02-12 17:36:46

+0

你能扩大你的答案吗?尽管对于高级java程序员来说答案可能很清楚,但它需要重新阅读这个问题才能完全理解你在说什么。我知道这可能是您以前的答案之一,但它出现在低质量帖子评论部分。 - [来自评论](https://stackoverflow.com/review/low-quality-posts/11445740) – Ferrybig 2016-02-29 08:53:25

1

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

超级消耗,延伸产生。

关于获取和放置原则,获得生产和消费。