Термин «стирание типа» на самом деле не является правильным описанием проблемы Java с обобщениями.
Стирание типов само по себе не является плохой вещью, оно очень необходимо для производительности и часто используется в нескольких языках, таких как C ++, Haskell, D.
Прежде чем вы испытаете отвращение, пожалуйста, вспомните правильное определение стирания типа из Wiki
Что такое стирание типа?
стирание типов относится к процессу загрузки, посредством которого явные аннотации типов удаляются из программы перед ее выполнением во время выполнения
Стирание типа означает отбрасывание тегов типа, созданных во время разработки, или предполагаемых тегов типа во время компиляции, так что скомпилированная программа в двоичном коде не содержит тегов типа.
И это относится к каждому языку программирования, компилируемому в двоичный код, за исключением некоторых случаев, когда вам нужны теги времени выполнения. Эти исключения включают в себя, например, все экзистенциальные типы (ссылочные типы Java, которые являются подтипами, любой тип во многих языках, объединенные типы).
Причиной стирания типов является то, что программы преобразуются в язык, который в некотором роде не типизирован (двоичный язык допускает только биты), поскольку типы являются только абстракциями и утверждают структуру своих значений и соответствующую семантику для их обработки.
Так что это взамен, нормальная естественная вещь.
Проблема Java в другом и вызвана тем, как она преобразуется.
Часто высказываемые утверждения о Java не имеют обобщенных обобщений, что также неверно.
Java исправляется, но неправильно из-за обратной совместимости.
Что такое овеществление?
Из нашей Wiki
Реификация - это процесс, с помощью которого абстрактное представление о компьютерной программе превращается в явную модель данных или другой объект, созданный на языке программирования.
Реификация означает преобразование чего-то абстрактного (Параметрический тип) в нечто конкретное (Конкретный тип) по специализации.
Мы проиллюстрируем это на простом примере:
ArrayList с определением:
ArrayList<T>
{
T[] elems;
...//methods
}
- это абстракция, в деталях конструктор типа, который становится «утонченным», когда специализируется на конкретном типе, скажем, Integer:
ArrayList<Integer>
{
Integer[] elems;
}
где ArrayList<Integer>
действительно тип.
Но это точно то, чего не делает Java !!! , вместо этого они постоянно связывают абстрактные типы со своими границами, то есть производят один и тот же конкретный тип независимо от передаваемых параметров по специальности:
ArrayList
{
Object[] elems;
}
, который здесь связан с неявным связанным объектом (ArrayList<T extends Object>
== ArrayList<T>
).
Несмотря на это, он делает непригодными универсальные массивы и вызывает странные ошибки для необработанных типов:
List<String> l= List.<String>of("h","s");
List lRaw=l
l.add(new Object())
String s=l.get(2) //Cast Exception
это вызывает много неясностей, как
void function(ArrayList<Integer> list){}
void function(ArrayList<Float> list){}
void function(ArrayList<String> list){}
относится к той же функции:
void function(ArrayList list)
и, следовательно, перегрузка универсального метода не может использоваться в Java.