Безопасно ли молча поймать ClasscastException при поиске определенного значения?
-
10-10-2019 - |
Вопрос
Предположим, я внедряю сортированную коллекцию (простой пример - Set
на основе отсортированного массива.) Рассмотрим эту (неполную) реализацию:
import java.util.*;
public class SortedArraySet<E> extends AbstractSet<E> {
@SuppressWarnings("unchecked")
public SortedArraySet(Collection<E> source, Comparator<E> comparator) {
this.comparator = (Comparator<Object>) comparator;
this.array = source.toArray();
Arrays.sort(this.array, this.comparator);
}
@Override
public boolean contains(Object key) {
return Arrays.binarySearch(array, key, comparator) >= 0;
}
private final Object[] array;
private final Comparator<Object> comparator;
}
Теперь давайте создадим набор целых чисел
Set<Integer> s = new SortedArraySet<Integer>(Arrays.asList(1, 2, 3), null);
И проверить, содержит ли он некоторые конкретные значения:
System.out.println(s.contains(2));
System.out.println(s.contains(42));
System.out.println(s.contains("42"));
Третья строка выше будет бросить ClassCastException
. Анкет Не то, что я хочу. Я бы предпочел, чтобы он вернулся false
(в качестве HashSet
делает.)
Я могу получить это поведение, поймав исключение и вернувшись:
@Override
public boolean contains(Object key) {
try {
return Arrays.binarySearch(array, key, comparator) >= 0;
} catch (ClassCastException e) {
return false;
}
}
Предполагая source
Коллекция правильно напечатана, что может пойти не так, если я сделаю это?
Решение
Я не думаю, что есть какие -либо проблемы с этим как Javadoc для Collection.contains
ясно гласит, что бросить ClassCastException
необязательно.
Единственный проблема Я вижу, если у тебя есть ошибка где-то Не бросить исключение, предотвратит его точно определить его.
Другие советы
А TreeSet
класс действительно бросает ClassCastException
для несовместимых аргументов contains()
(несовместимо для Comparator
используется набором). Так что нет ничего плохого в том, чтобы бросить это исключение. Просто убедитесь, что вы документируете, что это может произойти.
Совершенно законно позволить CCE бросить из Sontains (). Тем не менее, многие реализации коллекции поймают это и возвращают ложные, которые я считаю совершенно законным, и на самом деле является более удобным поведением.
В equals () у вас нет выбора; Вы должны поймать эту CCE.
Поймать неконтролируемое исключение всегда должно чувствовать себя грязно, но иногда это правильно.