这两个含糊不清的List.remove
是否有历史原因?
对我来说,这似乎是一种糟糕的设计
对于List<Integer>
,它似乎真的很混乱。
编辑:
每个人看起来都很好。让我精确一点。
假设我有List<Boolean>
。
Integer idx = Integer.valueOf(2);
list.remove(idx)
虽然idx
是一个对象,但Java会编译并删除索引2处的项目。
现在,如果它是List<Integer>
,那么相同的代码会调用另一种方法,但行为完全不同。
我们不要谈论泛型会发生什么。
我觉得不同的行为意味着不同的名字是一个宝贵的规则,尤其是在同一个班级内。
答案 0 :(得分:12)
首先:
List.remove(int)
删除指定索引和List.remove(Object)
(或Collection.remove(Object)
)删除指定的元素。我不确定这是否已经知道,但为了完整起见,我想我会提到它。
需要注意的一个重要部分是API早于泛型(更重要的是)自动装箱(Java 1.2中引入了集合API,Java 5中引入了自动装箱)。
因此,当他们第一次设计API时,绝对没有办法混淆这两者。即使您的List
包含Integer
个对象,也很简单:如果您使用原始参数类型(int
)调用该方法,那么如果您传入{{1},那么它就是索引(即使它是Object
),然后传入要删除的对象。
当然,它仍然仍然不是最好的主意(但是相当多的Java API ......不完美),但当时混淆的可能性要低得多。
由于自动装箱和自动拆箱,Integer
/ int
障碍变得不那么明显,因此只会出现混淆的可能性增加。
旁注:集合API的一个重要“特性”是“常用方法的简称”。 Vector
/ Enumeration
之前的“解决方案”因其常见的操作而闻名于世:
Integer
与Vector.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)
删除此指定元素列表中的第一个匹配项(可选操作)。如果此列表不包含该元素,则不会更改。
他们完成两件完全不同的事情,因此需要两者。