Почему Java TreeSet <E>remove (Object) не принимает E - PullRequest
8 голосов
/ 05 ноября 2011

С Java 6 TreeSet<E> Документация:

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

Почему это принимает Объект вместо универсального типа E? Единственные объекты, которые можно добавить, относятся к типу E, поэтому из этого следует, что единственный съемный тип должен иметь тип E.

Ответы [ 4 ]

9 голосов
/ 05 ноября 2011

Взяв ответ из первого опубликованного комментария:

Миф:

Популярный миф - это глупо и зло, но это было необходимо из-за обратной совместимости.Но аргумент совместимости не имеет значения;API корректен, независимо от того, считаете ли вы совместимость.

Реальная причина:

Равномерно методы платформы Java Collections Framework (и библиотеки Google Collections тоже) никогда не ограничиваюттипы их параметров, кроме случаев, когда необходимо предотвратить разрушение коллекции.

Подробнее читайте здесь: Почему Set.contains () принимает объект, а не E?

4 голосов
/ 05 ноября 2011

remove(), как и get(), требуется для работы, когда задан равный элемент (в терминах .equals()).В Java возможно (и в некоторых случаях требуется), чтобы объекты разных классов были равны.Следовательно, вы не должны ограничивать тип.

0 голосов
/ 05 ноября 2011

Это действительно проблема.Если кто-то вызывает remove(o) и тип o не E, это обычно программная ошибка, которая пытается удалить неправильную вещь.Проверка типов не смогла защитить нас от ошибки.

Хотя хорошая IDE (IntelliJ) может обнаруживать такие проблемы и предупреждать нас, разработчики API должны были предоставить более точную подпись для использования проверки типов компилятора.(IDE обманывает здесь - он знает значение Set.remove(), потому что это стандартный API. IDE не будет предоставлять такую ​​же справку для пользовательских API)

Для API запросов, таких как contains(), можно принятьне- E аргумент и вернуть тривиальное ложное.Таким образом, мы можем иметь оба

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

Для мутации API как remove(), это спорно, должен ли он принять не- E аргумент.Однако дебаты будут спорными, учитывая реальность стирания - на самом деле нет другого выбора, кроме как принять аргумент не-E и молчать об этом.Тем не менее, у нас может быть два метода

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

В большинстве случаев программисты могут вызывать contains2/remove2 для дополнительной безопасности типов.

0 голосов
/ 05 ноября 2011

Ну, каждое E также является Объектом, и, возможно, у вас есть E, не являющееся E в данный момент (например, из источника событий), что делает его удобным для вас. В противном случае вам просто нужно привести его к E, чтобы удалить его.

С точки зрения равенства это не имеет значения: адрес ссылки данного объекта проверяется, если он равен содержимому набора, поэтому не имеет значения, к какому классу он относится.

...