【问题标题】:Why is List.remove overloaded the way it is?为什么 List.remove 会按原样重载?
【发布时间】:2011-08-02 13:18:54
【问题描述】:

这两个模棱两可的List.remove有历史原因吗?

对我来说,这似乎是糟糕的设计。
对于 List<Integer> 来说,这似乎真的很令人困惑。

编辑:

每个人看起来都很好。让我稍微准确一点。

假设我有一个List<Boolean>

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

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

现在,如果它是 List<Integer>,那么相同的代码将调用具有完全不同行为的不同方法。

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

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

【问题讨论】:

  • List<Integer>的情况下,删除列表中的int的适当方法是使用remove(Integer.valueOf(number))

标签: java api list collections


【解决方案1】:

首先:

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

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

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

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

由于自动装箱和自动拆箱,int/Integer 屏障变得不那么明显,混淆的可能性才会增加。

旁注:集合 API 的一个重要“特性”是“常用方法的短名称”。 Vector/Enumeration 之前的“解决方案”对于非常常见的操作有着众所周知的长名称:

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

最后一个可能是他们走得太远了

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      什么,这根本不是模棱两可的。一个在指定的索引处删除,另一个在列表中第一次找到对象时删除它...... oO

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

      【讨论】:

      • @poulejapon,首先,我将您的评论标记为侮辱。其次,拥有多个具有不同参数/参数类型的方法是标准的 OO 实践。通过查看参数来解决歧义。
      • 对不起,如果你被冒犯了。我认为使用具有不同参数/参数类型的多态性确实是标准的 OO 实践,但仅当它们具有相同含义时。这里的行为是不同的。
      【解决方案4】:

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

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

      【讨论】:

      • 歧义恰恰是两个不同的事物具有相同的名称。
      • 它与设计无关,只是你可能会说的不好的命名。
      • @fmucar:命名 API 设计的一个非常重要的部分,我想说。如果我被称为ThingThatHoldsMultiplesOfOtherThingsCollection 就不是一回事了。
      • 我从来没有说过这不重要,如果您将 Collection 称为 ThingThatHoldsMultiplesOfOtherThings 那是您的错,而不是设计缺陷/错误。
      • 你可以称它为objectCollection、collectionOfObjects、objects、objectList、objectSet……这不是设计,而是编码约定。给设计师/建筑师起个好名字是开发者的责任。所以我想说的是,命名可能不好是的。而不是 remove(int) 也许它应该被称为 removeAtIndex(int) 或者更容易理解的东西。
      【解决方案5】:

      这怎么模棱两可?每种方法的文档对我来说似乎很清楚:

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

      boolean remove(Object o)
      删除此列表中第一个出现的指定元素(可选操作)。如果此列表不包含该元素,则它保持不变。

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

      【讨论】:

      • 是的,我两者都需要,但我希望它们有不同的名称(removeAt?removeValue?)
      猜你喜欢
      • 2015-05-04
      • 2013-06-06
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      相关资源
      最近更新 更多