Collections.min / max方法的签名
在Java中,Collections类包含以下方法:
public static <T extends Object & Comparable> T min(Collection c)
它的签名因其对generics的高级使用而闻名,因此在Java的Nutshell书籍和官方的Sun Generics Tutorial中都提到了它。
但是,我找不到令人信服的答案:
为什么Collection
的forms参数Collection
Collection
,而不是Collection
? 有什么额外的好处?
一个好处是?
是它禁止在Collection
添加项目
类型推断是一个棘手的话题,我承认我不太了解。 但是,请检查此示例:
public class ScratchPad { private static class A implements Comparable { public int compareTo(A o) { return 0; } } private static class B extends A {} private static class C extends B {} public static void main(String[] args) { Collection coll = null; B b = Scratchpad.min(coll); } public static > T min(Collection extends T> c) { return null; } //public static > T min(Collection c) { // return null; //} }
考虑min()的第一个签名允许调用编译而第二个签名不允许。 这不是一个非常实际的例子,因为我必须问为什么我会明确地将方法键入 ,但也许有一个隐式推理,其中
B
将是推断类型。
我认为它实际上并没有为这个方法提供更多的东西,但是当T是类的一部分而不仅仅是一个静态方法时,它是一个很好的习惯。
它们在这里包含它,所以它可以成为每个通用应该扩展的新约定?
一类T应遵循PECS: 什么是PECS(Producer扩展消费者超级)?
但是静态方法不需要(至少参数,返回值应该总是)
这是为了支持Java 1.4(以及之前)中方法的遗留签名。
在Java 5之前,这些方法的签名是
public static Object min ( Collection c );
使用多个边界时,擦除规则使第一个绑定方法的原始类型,因此没有Object &
签名
public static Comparable min ( Collection c );
和遗留代码会破裂。
这取自O’Reilly的Java Generics and Collections一书,第3.6章
根据我对Mark的答案提出的评论,如果你有类似的话
class Play { class A implements Comparable { @Override public int compareTo(A o) { return 0; } } class B extends A { } class C extends A { } public static > T min( Collection extends T> c) { Iterator extends T> i = c.iterator(); T candidate = i.next(); while (i.hasNext()) { T next = i.next(); if (next.compareTo(candidate) < 0) candidate = next; } return candidate; } public static List extends A> getMixedList() { Play p = new Play(); ArrayList c = new ArrayList(); c.add(p.new C()); c.add(p.new B()); return c; } public static void main(String[] args) { ArrayList c = new ArrayList(); Collection extends A> coll = getMixedList(); A a = Play.min(coll); } }
min更清楚的是返回A类型的对象(实际签名是 A Play.min(Collection extends A> c)
)。 如果你离开min(Collection
没有extends部分,那么Play.min(coll)
将具有以下签名 extends A> ? extends A Play.min(Collection extends A> c)
extends A> ? extends A Play.min(Collection extends A> c)
extends A> ? extends A Play.min(Collection extends A> c)
。