Как Type Erasure работает в Java?

Я просматривал тему TypeErasure по адресу http://download.oracle.com/javase/tutorial/java/generics/erasure.html, в котором говорится, что компилятор удаляет всю информацию, связанную с параметрами и аргументами типа внутри класса или метода.

Теперь рассмотрим код ниже

public class Box<T> {
    private T t; // lineA, T stands for "Type" 

    public void add(T t) { // lineB
        this.t = t; // lineC
    }

    public T get() { // lineD
        return t; // lineE
    }
}

Теперь внутри метода main у меня есть фрагмент кода ниже

Box<String> box1 = new Box<String>(); // line1
box1.add("Scott"); // line2
String s1tr=box1.get(); // line3

Box<Integer> box2 = new Box<Integer>(); // line4
box2.add(1); // line5
Integer k=box2.get(); // line6

Теперь в приведенном выше коде (в классе Box и методе main) какие изменения сделает компилятор и в какой строке?

Поскольку ссылка говорит, что компилятор удаляет всю информацию, связанную с параметрами типа и аргументами типа в классе или методе, когда компилятор будет компилировать класс Box, удалит ли он все вхождения T, <String>, <Integer> из класса Box и метода main соответственно? Если да, то каким будет скомпилированный код после удаления T?


person M Sach    schedule 10.09.2011    source источник
comment
Строка 4 в вашем примере не будет работать. Это вызовет ошибку компилятора, потому что типы (Box<Integer> и Box<String>) не совпадают.   -  person joschi    schedule 10.09.2011
comment
По большей части Type Erasure означает, что байтовому коду не нужно знать общий тип (генерируется некоторый дополнительный код), однако во многих отношениях это похоже на вызов Comment Erasure как функцию. ;)   -  person Peter Lawrey    schedule 10.09.2011
comment
Стирание типа - это не функция, это дженерики. Стирание типа — это выбор дизайна, сделанный при реализации дженериков, в обмен на выразительность ради бинарной совместимости.   -  person millimoose    schedule 10.09.2011


Ответы (2)


Стирание типа происходит во время компиляции. Компилятор Java удаляет эту информацию об универсальном типе из исходного кода и добавляет приведения по мере необходимости и доставляет байтовый код. Поэтому сгенерированный байт-код не будет содержать никакой информации о параметрах и аргументах типа. Это будет выглядеть как старый код Java без универсальных шаблонов. Невозможно определить значение T во время выполнения, поскольку эта информация удаляется до компиляции кода.

person Anthony    schedule 10.09.2011
comment
Для полноты в коде будет некоторая информация, оставшаяся от границ типов, и токены супертипа (gafter.blogspot.com/2006/12/super-type-tokens.html). Это означает, что в некоторых довольно специфических случаях вы можете восстановить значение T. - person millimoose; 10.09.2011
comment
Верно, я думаю, я хотел сказать, что не существует «надежного» способа определить типы. - person Anthony; 10.09.2011

При отсутствии границ типа, как в вашем примере кода, что (примерно) произойдет, что в классе Box все экземпляры всех ссылок на T в коде метода будут заменены на Object. В коде, использующем класс Box, все экземпляры <String>, <Integer> и т. д. будут удалены.

Исчерпывающая подробная статья о Java Generics находится в часто задаваемых вопросах Анжелики Лангер. границ типа и многое другое.

person millimoose    schedule 10.09.2011
comment
Да, согласен, что все экземпляры ‹T› будут удалены, а все ссылки на T будут заменены на Object. Но все же компилятор будет иметь некоторую информацию о метаданных после компиляции класса Box, чтобы когда на него ссылался другой класс, такой как основной метод в приведенном выше примере применяются проверки времени компиляции. Верно? - person M Sach; 10.09.2011
comment
@Mohit: Вероятно, вы правы, стирание типа влияет на код метода, а не на сигнатуры. Я отредактирую свой ответ, чтобы исправить это. - person millimoose; 10.09.2011