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 2

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"
}

Вы можете бросить ClassCastException в этом методе, поэтому вы не должны проверять тип. Прочитайте javadoc интерфейса коллекции.

Imho вы должны использовать методы equals / hashCode объекта parameter, чтобы проверить, присутствует ли он в вашей коллекции. Приведение или instanceof не требуется вообще.