ClassCastException vs instanceOf в универсальных коллекциях
У меня есть класс, который реализует Collection<E>
.
Когда я проверяю, содержит ли моя коллекция элемент, метод интерфейса дает параметр объекта, когда он должен быть <E>
Как вы думаете, это" нормально", чтобы написать этот код:
@Override
public boolean contains(Object o)
{
E item;
try
{
item=(E) o;
}
catch (ClassCastException e)
{
return false;
}
//check if contains "item"
}
Я знаю, что обычно это ужасная идея-проверять тип объекта с помощью try,catch
, но в универсальной коллекции я не могу проверить с помощью instanceOf
, и я не нахожу лучшего решения.4 ответа:
Из javadoc он говорит:
Throws: ClassCastException-если тип указанного элемента несовместим с этой коллекцией (необязательно)
Поэтому вполне допустимо закодировать его следующим образом:
@Override public boolean contains(Object o) { T item = (T) o; // ... }
И если бросок не удается, бросается
ClassCastException
.Вы, конечно, должны не скрывать это исключение и тихо возвращать
false
- это может оставить много потенциальных ошибок в коде пользователя.
Если ваш класс коллекции имеет
E
в качестве параметра универсального типа без границ, ваша проверка бесполезна - приведение не может завершиться ошибкой, потому что приведение полностью не проверено.E
, если он неограничен, стирается доObject
, и ваш бросок будетitem=(Object) o;
, который не может потерпеть неудачу. Это может привести к другим неудачам в других местах вниз по линии, но он не может потерпеть неудачу здесь, и если он потерпит неудачу в других местах позже, ваш try-catch не поймает его.Тот факт, что вы не можете использовать
instanceof
должен я вам кое-что сказал-Причина, по которойinstanceof
нельзя использовать, заключается в том, что это проверка во время выполнения, для проверки которой нужен класс во время выполнения, а у вас нет класса во время выполнения. Попытка получить сбой приведения также является проверкой во время выполнения, поэтому она не улучшает вашу ситуацию вообще. Полагаться на то, что приведение к неудаче работает только в тех же ситуациях, что иinstanceof
, поэтому никогда не имеет смысла "использовать приведение, потому чтоinstanceof
не работает".При написании универсального кода важно: рассмотрим, как выглядит код после стирания типа. Когда вы стираете универсальный код в неродовой код (добавляя приведения в соответствующих местах), код должен работать одинаково. Если невозможно написать код как неродовой, то он также не может быть написан как универсальный.
@Override public boolean contains(Object o) { Object item; try { item= o; } catch (ClassCastException e) // does this make sense? { return false; } //check if contains "item" }