5
public class Empty {

    public static void main( String[] args ) {

        TreeSet<Class> classes = new TreeSet<Class>();
        classes.add( String.class );

        String test = new String();

        try{ 
            if( classes.contains(test.getClass()) ){
                System.out.println( "contains" );
            }
        }catch(ClassCastException cce){

            System.out.println( "Expected:  "  + classes );
            System.out.println( "But it was: " + test.getClass() );
        }
    }
}

为什么这会抛出一个ClassCastException

4

4 回答 4

8

在没有显式比较器的情况下进行实例化时TreeSet,它期望插入的元素实现Comparable,但Class不实现此接口。

要修复,请创建一个比较器Class

Comparator<Class> classComp = new Comparator<Class>()
{
    @Override
    public int compare(Class o1, Class o2)
    {
        return o1.getName().compareTo(o2.getName());
    }
};
TreeSet<Class> classes = new TreeSet<Class>(classComp);
于 2010-08-17T11:45:58.787 回答
3

TreeSet是一个有序集,因此您插入的任何元素都必须实现Comparable(除非您指定自定义Comparator)。 Class才不是。

如果您不需要排序,则始终可以使用无序集,例如HashSet。否则,您将需要自己订购。

来自 Javadoc(强调我的):

基于 TreeMap 的 NavigableSet 实现。元素使用它们的自然顺序进行排序,或者由在集合创建时提供的 Comparator 排序,具体取决于使用的构造函数。

此实现为基本操作(添加、删除和包含)提供有保证的 log(n) 时间成本。

请注意,如果要正确实现 Set 接口,集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。(参见 Comparable 或 Comparator 以了解与 equals 一致的精确定义。)这是因为 Set 接口是根据 equals 操作定义的,但 TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,所以两个从集合的角度来看,这种方法认为相等的元素是相等的。一个集合的行为是明确定义的,即使它的顺序与equals不一致;它只是不遵守 Set 接口的一般约定。

另请参阅:比较器

于 2010-08-17T11:44:35.160 回答
1

Blockquote 为什么会抛出 ClassCastException?

这是由TreeMap的实现引起的,TreeSet是TreeMap的关键集,就是基于它。

java.lang.Class没有实现java.lang.Comparable接口,所以会抛出ClassCastException异常。

于 2010-08-17T12:34:27.697 回答
0

实际错误是java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.Comparable 。就是这样 - TreeSet 对元素进行排序。如果您使用 HashSet,一切正常。

于 2010-08-17T11:45:32.280 回答