是否要保持与Collection
的较旧(非通用化)版本的向后兼容性?还是有一个我错过的更细微的细节?我也在remove
(remove(Object o)
)中重复了这种模式,但add
被归为add(E e)
。
答案 0 :(得分:11)
contains()
需要Object
,因为它匹配的对象不必与传递给contains()
的对象的类型相同;它只要求它们是平等的。根据{{1}}的规范,如果存在contains()
对象contains(o)
,则e
返回true。请注意,没有任何内容要求(o==null ? e==null : o.equals(e))
和o
属于同一类型。这是因为e
方法接受equals()
作为参数,而不仅仅是与对象相同的类型。
虽然通常可以确定许多类已定义Object
,以使其对象只能等于其自己类的对象,但情况并非总是如此。例如,equals()
的规范表明,如果两个List.equals()
对象都是List
并且具有相同的内容,则它们是相等的,即使它们是List的不同实现。所以回到这个问题中的示例,可以有一个List
并且我可以用Collection<ArrayList>
作为参数调用contains()
,如果有一个LinkedList
,它可能会返回true具有相同内容的列表。如果contains()
是通用的并且将其参数类型限制为E
,那么这是不可能的。
事实上,contains()
将任何对象作为参数的事实允许一个有趣的用途,您可以使用它来测试集合中是否存在满足某个属性的对象:
Collection<Integer> 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;
}
});
答案 1 :(得分:5)
这里回答。
Why aren't Java Collections remove methods generic?
简而言之,他们希望最大限度地提高向后兼容性,因为收藏品早在仿制药之前就已经推出了。
从我这里补充一下:他所指的视频值得一看 http://www.youtube.com/watch?v=wDN_EYUvUq0
<强>更新强>
为了澄清,那个说(在视频中)是更新java地图和集合以使用泛型的人之一。如果他不知道,那么谁。
答案 2 :(得分:4)
这是因为contains
函数使用equals
函数,equals
函数在基础Object类中定义,签名为equals(Object o)
而不是{{ 1}}(因为并非所有类都是通用的)。与equals(E e)
函数相同的情况 - 它使用带有Object参数的remove
函数遍历集合。
然而,这并没有直接解释决定,因为他们仍然可以使用类型E并允许它在调用equals
时自动转换为对象类型;但我想他们想要允许在其他Object类型上调用该函数。拥有equals
然后调用Collection<Foo> c;
没有任何问题 - 它总是返回false,因此它不需要强制转换类型Foo(可以抛出异常),或者保护例外,c.contains(somethingOfTypeBar)
电话。所以你可以想象如果你在使用混合类型迭代并在每个元素上调用typeof
,你可以简单地在所有元素上使用contains函数而不需要守卫。
当你以这种方式看待它时,它实际上让人想起“更新”的松散型语言......
答案 3 :(得分:0)
因为否则它只能与参数类型的完全匹配进行比较,特别是通配符集合将停止工作,例如。
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
修改强>
对于那些认为不是其中一个原因的怀疑者,这里是一个修改后的数组列表,其中包含一个包含方法
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一起使用的黑客。
答案 4 :(得分:0)
“那篮子里的苹果含有这种橙子吗?”
显然无法给出正确答案。但这仍然有可能:
收集api选择了第一个。但第二选择也很有意义。像这样的问题是99.99%的废话问题,所以甚至不要问!