为什么List.remove会以它的方式重载?

时间:2011-08-02 13:18:54

标签: java api list collections

这两个含糊不清的List.remove是否有历史原因?

对我来说,这似乎是一种糟糕的设计 对于List<Integer>,它似乎真的很混乱。

编辑:

每个人看起来都很好。让我精确一点。

假设我有List<Boolean>

Integer idx = Integer.valueOf(2);
list.remove(idx)

虽然idx是一个对象,但Java会编译并删除索引2处的项目。

现在,如果它是List<Integer>,那么相同的代码会调用另一种方法,但行为完全不同。

我们不要谈论泛型会发生什么。

我觉得不同的行为意味着不同的名字是一个宝贵的规则,尤其是在同一个班级内。

5 个答案:

答案 0 :(得分:12)

首先:

我不确定这是否已经知道,但为了完整起见,我想我会提到它。

需要注意的一个重要部分是API早于泛型(更重要的是)自动装箱(Java 1.2中引入了集合API,Java 5中引入了自动装箱)。

因此,当他们第一次设计API时,绝对没有办法混淆这两者。即使您的List包含Integer个对象,也很简单:如果您使用原始参数类型(int)调用该方法,那么如果您传入{{1},那么它就是索引(即使它是Object),然后传入要删除的对象。

当然,它仍然仍然不是最好的主意(但是相当多的Java API ......不完美),但当时混淆的可能性要低得多。

由于自动装箱和自动拆箱,Integer / int障碍变得不那么明显,因此只会出现混淆的可能性增加。

旁注:集合API的一个重要“特性”是“常用方法的简称”。 Vector / Enumeration之前的“解决方案”因其常见的操作而闻名于世:

  • IntegerVector.elementAt()
  • List.get()Vector.addElement()
  • Collection.add() / Enumeration.hasMoreElements()nextElement() / Iterator.hasNext()
  • next()Vector.removeElement()
  • Collection.remove()Vector.removeElementAt()

最后一个是他们可能有点远的地方。

答案 1 :(得分:2)

是的,这个确切的案例经常被引用作为一个例子,说明善意的语言变化(泛型,自动装箱)如何相互结合,并与现有的API结合产生错误。事实上Josh希望他给方法赋予不同的名称,但是当首次创建该接口时,从未想到Object和int之间可能存在任何冲突。您可以在Java Puzzlers(Bloch / Gafter)中找到对此问题的探索。

答案 2 :(得分:0)

什么,这根本不是暧昧的。一个在指定的索引处移除,另一个移除了一个对象 - 它首先在列表中找到... oO

编辑 - 方法的定义不仅仅是名称。参数的类型和数量是定义的一部分。当你采用整个方法定义时,没有歧义。

答案 3 :(得分:0)

其中一个是从特定索引中删除

另一个是删除对象,索引并不重要。

答案 4 :(得分:-3)

这有多么模棱两可?我觉得每种方法的文档都很清楚:

  

E remove(int index)
  删除此列表中指定位置的元素(可选操作)。

     

boolean remove(Object o)
  删除此指定元素列表中的第一个匹配项(可选操作)。如果此列表不包含该元素,则不会更改。

他们完成两件完全不同的事情,因此需要两者。