为什么我们有包含(Object o)而不是contains(E e)?

它是否与旧的(非泛化)版本的Collection保持向后兼容? 还是有一个我错过的更细微的细节? 我也看到这个模式在remove重复removeremove(Object o) ),但是add被泛化为add(E e)

contains()接受一个Object因为它匹配的对象不必与传入contains()的对象类型相同; 它只要求它们是平等的。 根据contains()的规范,如果有一个对象e使得(o==null ? e==null : o.equals(e))为真,则contains(o)返回true。 请注意,没有什么要求oe是相同的类型。 这是因为equals()方法将Object作为参数,而不仅仅是与对象相同的类型。

虽然通常可以确定许多类定义了equals() ,以使其对象只能等于其自己的类的对象,但情况并非总是如此。 例如, List.equals()的规范说如果它们都是List并且具有相同的内容,则两个List对象是相等的,即使它们是List的不同实现。 回到这个问题的例子,可以有一个Collection并且我可以使用LinkedList作为参数调用contains() ,如果有一个具有相同内容的列表,它可能返回true。 如果contains()是通用的并且将其参数类型限制为E则这是不可能的。

事实上, contains()接受任何对象作为参数允许一个有趣的用途,你可以使用它来测试集合中是否存在满足某个属性的对象:

 Collection integers; boolean oddNumberExists = integers.contains(new Object() { public boolean equals(Object e) { Integer i = (Integer)e; if (i % 2 != 0) return true; else return false; } }); 

这里回答。
为什么Java Collections没有删除generics方法?
简而言之,他们希望最大限度地提高向后兼容性,因为在generics之前很久就会引入集合。

从我这里补充一下:他所指的video值得关注。
http://www.youtube.com/watch?v=wDN_EYUvUq0

更新
为了澄清,那个说(在video中)是更新java地图和集合以使用generics的人之一。 如果他不知道,那么谁。

这是因为contains函数使用equals函数,而equals函数在基类Object类中定义,其签名为equals(Object o)而不是equals(E e) (因为并非所有类都是通用的)。 与remove函数的情况相同 – 它使用带有Object参数的equals函数遍历集合。

然而,这并没有直接解释决定,因为他们仍然可以使用类型E并允许它在调用equals自动转换为Object类型; 但我想他们想要允许在其他Object类型上调用该函数。 拥有Collection c;没有任何问题Collection c; 然后调用c.contains(somethingOfTypeBar) – 它将始终返回false,因此它不需要c.contains(somethingOfTypeBar)转换类型Foo(可以抛出exception),或者为了防止exception,需要调用typeof 。 所以你可以想象如果你在使用混合类型迭代并在每个元素上调用contains ,你可以简单地在所有元素上使用contains函数而不需要保护。

它实际上让人联想到“更新”的松散型语言,当你以这种方式看待它时……

因为否则它只能与参数类型的完全匹配进行比较,特别是通配符集合将停止工作,例如

 class Base { } class Derived extends Base { } Collection< ? extends Base > c = ...; Derived d = ...; Base base_ref = d; c.contains( d ); // Would have produced compile error c.contains( base_ref ); // Would have produced compile error 

编辑
对于那些认为不是其中一个原因的怀疑者,这里是一个修改后的数组列表,其中包含一个generified包含方法

 class MyCollection< E > extends ArrayList< E > { public boolean myContains( E e ) { return false; } } MyCollecttion< ? extends Base > c2 = ...; c2.myContains( d ); // does not compile c2.myContains( base_ref ); // does not compile 

基本上contains( Object o )是使这个非常常见的用例与Java Generics一起使用的hack。

“那篮子里的苹果含有这种橙子吗?”

显然无法给出正确的答案。 但这仍然有可能:

  1. 答案是假的。
  2. 问题形成不好,不应该通过编译。

收集api选择了第一个。 但第二选择也很有意义。 像这样的问题是99.99%的废话问题,所以甚至不要问!