为什么Java的TreeSet <e> remove(Object)不带E </e>

时间:2011-11-04 21:06:05

标签: java generics collections treeset

来自Java 6 TreeSet<E>文档:

boolean remove(Object o):
    Removes the specified element from this set if it is present.

为什么这会接受Object而不是通用类型E?唯一可以添加的对象是E类型,因此唯一的可移动类型应该是E类型。

4 个答案:

答案 0 :(得分:9)

从第一条评论中回答:

神话:

  

一个流行的神话是它是愚蠢和邪恶的,但确实如此   因向后兼容而必要。但兼容性   论证是无关紧要的;无论你考虑,API都是正确的   兼容性与否。

真正的原因:

  

统一地,Java Collections Framework(和Google   集合库也绝不限制其参数的类型   除非有必要防止收集   碎。

在此处阅读更多内容:Why does Set.contains() take an Object, not an E?

答案 1 :(得分:4)

remove(),与get()一样,在给定相等的元素时需要工作(就.equals()而言)。在Java中,不同类的对象可能(在某些情况下是必需的)是相同的。因此,您不应该限制类型。

答案 2 :(得分:0)

好吧,每个E也是一个对象,也许你现在的E不是E(例如来自事件源),这对你来说很方便。否则你只需将其强制转换为E即可将其删除。

从平等的角度来看,这并不重要:如果给定对象的引用地址等于集合的内容,则对其进行测试,因此它与哪个类无关。

答案 3 :(得分:0)

这确实是一个问题。如果有人调用remove(o)o的类型不是E,则通常是编程错误,尝试删除错误的内容。类型检查无法保护我们免受错误。

虽然一个好的IDE(IntelliJ)可以检测到这些问题并警告我们,但API设计者应该提供更精确的签名来利用编译器类型检查。 (IDE在这里作弊 - 它知道Set.remove()的含义,因为它是标准API.IDE不会为自定义API提供相同的帮助)

对于像contains()这样的查询API,可以接受非E参数并返回一个简单的false。所以我们可以同时拥有

boolean contains(Object o);
boolean contains2(E o);

对于像remove()这样的变异API,它是否应该接受非E参数是值得商榷的。然而,鉴于擦除的现实,辩论将没有实际意义 - 除了接受非E论证并对此保持沉默之外别无选择。我们仍然可以有两种方法

boolean remove(Object o);
boolean remove2(E o);

在大多数情况下,程序员可以调用contains2/remove2以获得额外的类型安全性。