为什么SomeClass 不等同于Javagenerics类型中的SomeClass ?
我注意到了Collections.sort的具体说明:
public static void sort(List list, Comparator c)
为什么这里需要“ ? super
”? 如果ClassB
扩展了ClassA
,那么我们不能保证Comparator
能够比较两个ClassB
对象,而没有“ ? super
”部分吗?
换句话说,鉴于此代码:
List list = . . . ; Comparator comp = . . . ; Collections.sort(list, comp);
为什么编译器不够聪明,即使没有为Collections.sort()的声明指定“ ? super
”,也知道这没关系?
Josh Bloch今年在Google I / O上发表了一篇名为Effective Java Reloaded的演讲,您可能会感兴趣。 它谈到了一个名为“Pecs”(生产者extends
,消费者super
)的助记符,它解释了你使用的原因? extends T
? extends T
和? super T
输入参数中的? super T
(仅用于返回类型),以及何时使用哪些。
在使用通配符更有趣的情况下,有一个非常好(但有点曲折)的解释。
这类似于C#,我刚刚了解了它为什么(艰难的方式,然后是PDC信息方式)。
假设Dog extends Animal
Blah
与Blah
不同,即使Dog
扩展Animal
它们也有完全不同的类型签名。
例如假设Blah
上的方法:
T Clone();
在Blah
这是Dog Clone();
而在Blah
这是Animal Clone();
。
您需要一种方法来区分编译器可以说Blah
具有与Blah
相同的公共接口,那就是 super T>
super T>
表示 – 任何用作T的类都可以用Blah super T>
Blah super T>
。
(在C#4.0中,这将是Blah
我相信。)
很明显,对于Comparator
,任何T
祖先都可以工作。 但是编译器不知道类Comparator
function就是这样 – 只需要告诉它是否应该允许
或 super T>
super T>
。
从另一个角度来看,是的,祖先的任何Comparator
都可以在这种情况下工作 – 而且库开发人员说这是使用 super T>
super T>
。
对您的问题的简单回答是,图书馆设计师希望为图书馆的用户提供最大的灵活性; 例如,此方法签名允许您执行以下操作:
List ints = Arrays.asList(1,2,3); Comparator numberComparator = ...; Collections.sort(ints, numberComparator);
使用通配符可以防止您被强制使用Comparator
; 该语言要求库设计者指定通配符这一事实使他或她能够允许或限制此类使用。