Почему List.remove перегружен так, как есть? - PullRequest
9 голосов
/ 02 августа 2011

Есть ли исторические причины для двух неоднозначных List.remove?

Мне кажется, что это ужасный дизайн.
Для List<Integer> это выглядит просто сбивающим с толку.

РЕДАКТИРОВАТЬ:

Все, кажется, довольно хорошо с этим.Позвольте мне немного уточнить.

Допустим, у меня есть List<Boolean>.

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

Хотя idx является объектом, Java компилируется и удаляет элемент по индексу 2.

Теперь, если бы это был List<Integer>, тот же самый код вызвал бы другой метод с совершенно другим поведением.

Давайте не будем говорить о том, что произойдет с Generics.

Мне кажется, разное поведение подразумевает разные имена - драгоценное правило, особенно внутри одного класса.

Ответы [ 5 ]

12 голосов
/ 02 августа 2011

Прежде всего:

Я не уверен, было ли это уже известно, но ради полноты я подумал, что упомяну это.

Важной частью, на которую следует обратить внимание, является то, что API предшествует универсальному (и, что более важно,) автобоксированию (API коллекций был введен в Java 1.2, а автобокс - в Java 5).

Поэтому, когда они впервые разработали API, не было никакого способа перепутать их. Даже если ваши List содержали Integer объектов, все просто: если вы вызываете метод с примитивным типом аргумента (int), то это индекс, если вы передаете Object (даже если это * 1030) *), затем вы передаете объект для удаления.

Конечно, это все еще не самая лучшая идея (но довольно много API Java ... не идеальны), но вероятность путаницы была намного ниже.

Повышенная вероятность путаницы существует только потому, что барьер int / Integer стал менее видимым благодаря автоматическому боксу и автоматической распаковке.

Sidenote: важной «особенностью» 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 голосов
/ 03 августа 2011

Да, именно этот случай часто приводят в качестве примера того, как совершенно благонамеренные языковые изменения (обобщение, автобокс) могут сочетаться друг с другом и с существующими API для получения ошибок. Действительно, Джош хотел бы, чтобы он дал методам разные имена, но когда этот интерфейс был впервые создан, никогда не предполагалось, что может быть какой-либо конфликт между Object и int. Вы можете найти исследование этой проблемы в Java Puzzlers (Bloch / Gafter).

0 голосов
/ 02 августа 2011

Один из них предназначен для удаления из определенного индекса

Другой объект удаляет объект, индекс не важен.

0 голосов
/ 02 августа 2011

Как это двусмысленно?Документация по каждому методу кажется мне понятной:

E remove(int index)
Удаляет элемент в указанной позиции в этом списке (необязательная операция).

boolean remove(Object o)
Удаляет первое вхождение в этом списке указанного элемента (необязательная операция).Если этот список не содержит элемент, он не изменяется.

Они делают две совершенно разные вещи, отсюда необходимость в обоих.

0 голосов
/ 02 августа 2011

Что, это совсем не амбициозно. Один удаляет по указанному индексу, другой удаляет объект, где бы он ни был впервые найден в списке ... oO

РЕДАКТИРОВАТЬ - определение метода больше, чем просто имя. Тип и количество аргументов является частью определения. Когда вы берете полное определение метода, нет никакой двусмысленности.

...