4

假设我正在实现一个排序集合(简单示例 -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这样。)

我可以通过捕获异常并返回 false 来获得这种行为:

@Override    
public boolean contains(Object key) {
    try {
        return Arrays.binarySearch(array, key, comparator) >= 0;
    } catch (ClassCastException e) {
        return false;
    }
}

假设source集合是正确输入的,如果我这样做会出现什么问题?

4

3 回答 3

3

我认为这没有任何问题,因为 JavadocCollection.contains明确指出抛出 aClassCastException是可选的。

我看到的唯一问题是,如果您在某个地方有错误,但不会引发异常,则会阻止您查明它。

于 2011-01-12T22:18:07.423 回答
1

该类TreeSet确实抛出了一个ClassCastException不兼容的参数到contains()(不兼容Comparator的集合使用)。因此,抛出该异常并没有错。只要确保您记录这可能会发生。

于 2011-01-12T23:00:04.120 回答
1

让 CCE 从 contains() 中抛出是完全合法的。但是,许多集合实现捕获并返回 false,我认为这也是完全合法的,实际上是更用户友好的行为。

在 equals() 你没有选择;你必须赶上那个CCE。

捕获未经检查的异常应该总是让人觉得很脏,但有时这是正确的做法。

于 2011-01-19T19:57:33.227 回答