Важной особенностью параметрических типов является способность писать полиморфные алгоритмы, то есть алгоритмы, которые работают с структурой данных независимо от значения ее параметра, например Arrays.sort()
.
С обобщениями это делается с подстановочными типами:
<E extends Comparable<E>> void sort(E[]);
Чтобы быть действительно полезными, подстановочные типы требуют подстановочного знака, а для этого требуется понятие параметра типа. Ничего из этого не было доступно в то время, когда массивы были добавлены в Java, а создание массивов ссылочного типа ковариантно позволило намного проще разрешить полиморфные алгоритмы:
void sort(Comparable[]);
Однако эта простота открыла лазейку в системе статического типа:
String[] strings = {"hello"};
Object[] objects = strings;
objects[0] = 1; // throws ArrayStoreException
требует проверки во время выполнения каждого доступа на запись в массив ссылочного типа.
Короче говоря, новый подход, воплощенный в дженериках, делает систему типов более сложной, но также более статически безопасной, в то время как более старый подход был проще и менее статически безопасен. Разработчики языка выбрали более простой подход, имея более важные дела, чем закрытие небольшой лазейки в системе типов, которая редко вызывает проблемы. Позже, когда была создана Java и были решены насущные потребности, у них были ресурсы, чтобы сделать это правильно для обобщений (но изменение его для массивов могло бы сломать существующие программы Java).