对于强制比较类型的集合,抛出运行时异常比编译时检查有什么好处?
What are the benefits of throwing runtime exceptions over compile time checks for collections that enforce comparable types?
在实现我自己的需要可比较类型的数据结构时,我总是这样做:
public class ComparableCollection<E extends Comparable<E>> { ... }
这显然在编译时强制执行了可比约束。但是我在过去几年一直是一名学生,并且不知何故忽略了这样一个事实,即强制执行可比较类型的集合的 Java 实现不会在编译时这样做,而是在运行时通过可能抛出 ClassCastException
同时添加一个元素;例如:
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, ... { ... }
TreeSet
由 NavigableMap
支持,如果 Comparator
是 null
,则尝试像这样转换密钥:
Comparable<? super K> k = (Comparable<? super K>) key;
现在,如果插入的类型不可比较,则会抛出 ClassCastException
。
与在编译时强制执行约束相比,此设计的真正好处是什么?
好处是您可以将 TreeSet 与未实现 Comparable
但您可以为其提供 Comparator
的对象一起使用。
有关 Comparable 和 Comparator 之间差异的更多信息,请参阅:Java : Comparable vs Comparator
您始终无法控制在编译时将哪些对象插入到集合中。允许动态定义集合更加灵活。
在实现我自己的需要可比较类型的数据结构时,我总是这样做:
public class ComparableCollection<E extends Comparable<E>> { ... }
这显然在编译时强制执行了可比约束。但是我在过去几年一直是一名学生,并且不知何故忽略了这样一个事实,即强制执行可比较类型的集合的 Java 实现不会在编译时这样做,而是在运行时通过可能抛出 ClassCastException
同时添加一个元素;例如:
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, ... { ... }
TreeSet
由 NavigableMap
支持,如果 Comparator
是 null
,则尝试像这样转换密钥:
Comparable<? super K> k = (Comparable<? super K>) key;
现在,如果插入的类型不可比较,则会抛出 ClassCastException
。
与在编译时强制执行约束相比,此设计的真正好处是什么?
好处是您可以将 TreeSet 与未实现 Comparable
但您可以为其提供 Comparator
的对象一起使用。
有关 Comparable 和 Comparator 之间差异的更多信息,请参阅:Java : Comparable vs Comparator
您始终无法控制在编译时将哪些对象插入到集合中。允许动态定义集合更加灵活。