Search code examples
javadata-structurescomparable

What are the benefits of throwing runtime exceptions over compile time checks for collections that enforce comparable types?


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?


Solution

  • The benefit is that you can then use TreeSet with objects that do not implement Comparable but for which you can provide a Comparator.

    For more about the differences between Comparable an Comparator, see: Java : Comparable vs Comparator