When implementing my own data structures which require a comparable type I've always done so like this:
public class ComparableCollection<E extends Comparable<E>> { ... }
This obviously enforces the comparable constraint at compile time. But I've been a student for the last couple years and have somehow overlooked the fact that the Java implementations for collections that enforce a comparable type do not do so at compile time but rather at runtime by possibly throwing a ClassCastException
while adding an element; e.g.:
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, ... { ... }
TreeSet
is backed by a NavigableMap
which, if it's Comparator
is null
, attempts to cast the key like so:
Comparable<? super K> k = (Comparable<? super K>) key;
Now, if the type being inserted isn't comparable a ClassCastException
is thrown.
What are the real benefits of this design over enforcing the constraint at compile time?