2008-10-30 66 views
7

我注意到了Collections.sort的specificaition:为什么SomeClass <? super T>不等于Java泛型中的SomeClass <T>?

public static <T> void sort(List<T> list, Comparator<? super T> c) 

为什么 “? super” 必要吗?如果ClassB扩展为ClassA,那么我们不能保证Comparator<ClassA>能够比较两个ClassB对象,没有“? super”部分?

换句话说,鉴于此代码:

List<ClassB> list = . . . ; 
Comparator<ClassA> comp = . . . ; 
Collections.sort(list, comp); 

为什么不是编译器足够聪明,知道这是OK,即使没有指定“? super”为Collections.sort的声明()?

回答

7

Josh Bloch今年在Google I/O上进行了一次演讲,名为Effective Java Reloaded,您可能会感兴趣。它讲述了一个名为“Pecs”的助记符(生产商extends,消费者super),这就解释了为什么在输入参数中使用? extends T? super T(仅限于;从不使用返回类型)以及何时使用哪个。

+0

谢谢,这是一个有用的演示文稿。我认为我的问题的根源是第一张真正的幻灯片:列表不是列表的子类,其方式是String []是Object []的子类。 – Kip 2008-10-30 19:42:43

0

很明显,在Comparator的情况下,任何一个T的祖先都可以工作。但是编译器并不知道类Comparator这样的功能 - 只需要知道它应该允许<T>还是<? super T>

从另一种角度看,是的,任何一个祖先的Comparator都可以在这种情况下工作 - 而图书馆开发人员说的方式是使用<? super T>

+0

但它不仅对我很明显 - 比较器意味着它有一些函数只能用于T类型的对象。因为ClassB的所有对象都是ClassA的对象,所以比较器的所有功能都只适用于ClassA也在ClassB上工作。 AFAIK – Kip 2008-10-30 19:13:40

1

这与C#类似,前两天我刚刚了解到它的原因(困难的方法,然后是PDC的信息方式)。

假设Dog extends Animal

Blah<Dog>一样Blah<Animal>他们即使Dog延伸Animal完全不同类型的签名。

例如,假设上Blah<T>的方法:

T Clone(); 

Blah<Dog>这是Dog Clone();而在Blah<Animal>这是Animal Clone();

您需要一种方法来区分编译器可以说Blah<Dog>Blah<Animal>相同的公共接口,这就是<? super T>指示 - 使用为T任何类都可以在Blah<? super T>方面减少到其超类。

(在C#4.0中,这将是Blah<out T>我相信。)

0

对你的问题的简单回答是,图书馆设计者想给图书馆用户提供最大的灵活性;例如这种方法签名可以让你做这样的事情:

List<Integer> ints = Arrays.asList(1,2,3); 
Comparator<Number> numberComparator = ...; 

Collections.sort(ints, numberComparator); 

使用通配符防止您被强制使用Comparator<Integer>;图书馆设计者指定该语言需要通配符的事实使他或她能够允许或限制这种使用。

相关问题