Создание TreeSet с классом non-Comparable: почему исключение во время выполнения, а не ошибка времени компиляции?

Если я создаю произвольный класс, который не реализует Comparable, и попытается использовать его как treeet, он выдает исключение во время выполнения, когда объект вставлен:

public class Foo {
}

public TreeSet<Foo> fooSet = new TreeSet<Foo>();
fooSet.add(new Foo()); // Throws a ClassCastException exception here: Foo is not comparable

Я не эксперт по Java, но что-то об этом казалось динамически типизированным (ala Python) таким образом, которого я не ожидал. Нет ли способа реализации TreeSet указать, что его аргумент generic type должен реализовывать Comparable, чтобы это можно было поймать во время компиляции? Не общие функции могут принимать интерфейсы в качестве аргументов; такое же невозможное с дженериками?

Ответ 1

TreeSet реализуется таким образом, потому что вы можете альтернативно предоставить Comparator, и в этом случае элементы не должны быть Comparable. Единственный способ поддерживать оба поведения без разделения реализации на несколько классов состоял в том, чтобы включать проверки времени выполнения - это было просто дизайнерское решение автора (ов) этого класса.

TreeSet фабричных методов TreeSet вместо публичных конструкторов было бы способом поддерживать проверку времени компиляции с использованием более строгих ограничений типа общего типа, но это было бы отрыв от соглашения API коллективных коллекций об экспонировании открытых конструкторов no-arg и copy для его классы реализации. Как вы отметили в своем комментарии, Гува отправляется на заводский маршрут со своими коллекциями, и имхо лучше для него.