If I create an arbitrary class that does not implement Comparable, and try to use it as a treeset, it throws an exception at run time when an object is inserted:
public class Foo {
}
public TreeSet<Foo> fooSet = new TreeSet<Foo>();
fooSet.add(new Foo()); // Throws a ClassCastException exception here: Foo is not comparable
I’m no Java expert, but something about this seemed dynamically typed (ala Python) in a way I wasn’t expecting. Is there no way for TreeSet’s implementation to specify that its generic type argument must implement Comparable so that this can be caught at compile-time? Non-generic functions can take interfaces as arguments; is the same not possible with generics?
TreeSetis implemented that way because you can alternatively provide aComparator, in which case the elements don’t need to beComparable. The only way to support both behaviors without splitting the implementation into multiple classes was to include runtime checks – this was simply a design decision by the author(s) of that class.Exposing factory methods for
TreeSetinstead of public constructors would’ve been a way to maintain compile time checks using stricter generic type constraints, but that would’ve been a break from the core collections API’s convention of exposing public no-arg and copy constructors for its implementation classes. As you noted in your comment, Guava goes the factory route with its collections and IMHO is better off for it.