我在使用TreeSet时,在调用TreeSet#add()方法时找到了一个ClassCastException。
代码:
public class Testing {
public static void main(String[] args) {
TreeSet<Testing> ts = new TreeSet<>();
ts.add(new Testing());
}
}输出:
Exception in thread "main" java.lang.ClassCastException: Testing cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1290)
at java.util.TreeMap.put(TreeMap.java:538)
at java.util.TreeSet.add(TreeSet.java:255)
at Testing.main(Testing.java:13)显然,这是因为TreeSet是一个有序集合,它需要Comparable对象来对它们进行排序,那么为什么不将其类型声明为
public class TreeSet<E extends Comparable<E>>并在编译时进行检查,而不是在运行时抛出异常?
发布于 2016-03-03 11:19:28
TreeSet的元素不必实现Comparable,因为您可以将Comparator传递给TreeSet的构造函数之一,以便对不实现Comparable的元素(或者当您希望使用Comparable定义的自然排序以外的排序时确实实现Comparable的元素)强制排序。
发布于 2016-03-03 11:31:33
正如在其他答案中提到的,如果指定了自定义TreeSet,那么Comparable键可能不是Comparator。仍然有可能对您的情况执行编译时检查。假设我们将默认构造函数设置为私有,并提供一个静态工厂方法:
public class TreeSet<E> {
private TreeSet() {...}
public static <E extend Comparable<? super E>> TreeSet<E> newSet() {
return new TreeSet<>();
}
}这样,您将被迫使用TreeSet.newSet(),如果将编译时类型检查分配给TreeSet<Testing>,并且Testing是不可比拟的,那么编译时类型检查就会失败。为什么不做呢?因为泛型只出现在Java1.5中,而TreeSet出现在Java1.2中,所以这不是一个问题。现在我们必须处理向后兼容性问题。
发布于 2016-03-03 11:28:33
按照它的实现方式,您可以订购那些无法自行决定是否应该在较高或较低的位置上订购的项目。
以现实生活为例:你有一场选美比赛。如果你问其中一个女孩她是否比她旁边的那个漂亮,她会说是的。你不能仅仅通过问他们就把他们按顺序排列。所以你需要其他人来负责排序,比较器。
这允许您订购无法将自己与另一项进行比较的项目。
https://stackoverflow.com/questions/35770730
复制相似问题