@WTFAYD

Почему информация о типе сохраняется, несмотря на стирание типов?

class Generic<T> {
    T obj;
    void set(T obj) { this.obj = obj; }
    T get() { return obj; }
}
public class Program {
    static public void main(String[] args) {
        Generic<String> g = new Generic<>();
        Generic<Integer> f = new Generic<>();
        g.set("String");
        f.set(123);
        System.out.println(g.get() + f.get());
    }
}


Вывод, соответственно, как и ожидается, String123. Возникает вопрос - что делает компилятор, когда создается экземпляр параметризованного типа - ищет .class файл, инициализирует переменные как в обычном классе, но вместо T указывает Object? Тогда как компилятор узнает точный параметр типа, если информация о типах стирается до Object? Дело в bridge methods?
  • Вопрос задан
  • 713 просмотров
Пригласить эксперта
Ответы на вопрос 1
SlandShow
@SlandShow
70% of my body is made of movies.
Сначала может показаться, что JVM создает новую версию класса где и заменяет Т на нужный тип. Но на самом деле, JVM частично 'подправляет' уже имеющийся параметризованный класс. В том числе заменяет Т на версию нужного значения каждый раз, когда это требуется. Т.е класс существует один, а не несколько версий с полями разных типов.

В вашем же случае сначала JVM подправляет T obj на Object obj (который преобразуется нисходящим преобразованием в String) а потом снова подправляет String obj на Object obj (который потом так-же преобразуется в Integer неявно)

g.set("String");
f.set(123);



T obj на самом деле заменяется на Object obj. Этот процесс называется стиранием, который происходит на стадии компиляции. А затем неявно происходит нисходящее преобразование.
class Test<T> {
T val; // на самом деле T заменяется на Object
Test(T o) { val = o; }
T get() { return val; }

}

class SimpleClass {
void info() { System.out.println("я метод info() из класса SimpleClass"); }
}

Test<SimpleClass> v = new Test<>(new SimpleClass());

SimpleClass v2 = v.get(); // при инициализации v2 на самом деле происходит неявное нисходящее преобразование к нужному типу

//что происходит на самом деле:
//SimpleClass v2 = (SimpleClass) v.get();

v2.info();


Стирание генерализированных типов происходит на стадии компиляции. В самом простом случае ничем не ограниченный тип стирается до Object`а, обобщенный класс NameClass до NameClass.

Другими словами информация о дженериках существует только на этапе компиляции и недоступна в runtime.

Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы