Type erasure (стирание типов) в Java — это такой однажды вставленный в язык костыль для поддержки generics — параметризации типов у классов/методов. Нужен он был для совместимости байткода с предыдущими версиями Java, а заключается он в том, что проверка на соответствие типов данных в generics производится исключительно во время компиляции, а не во время выполнения.
Из этого следует то, что можно обхитрить систему во время компиляции и попробовать этим воспользоваться для запутывания самих себя в рантайме.
Итак, код.
private static class Foo<T> {
T value1, value2;
public void print() {
System.out.println(value1);
System.out.println(value2);
}
}
public static <T> Foo<T> create(Object o1, Object o2) {
Foo<T> result = new Foo<T>();
result.value1 = (T) o1;
result.value2 = (T) o2;
return result;
}
public static void main(String[] args) {
Double pi = 3.14;
String hello = "hello";
Foo<Integer> test = create(pi, hello);
test.print();
}
Суть кода: создаём объект класса Foo
Логично предположить, что приложение ругнётся на этот код, так как несоответствие типов данных налицо. Однако же результатом работы будет следующий вывод:
3.14
hello
Что же случилось? Стёрлись типы. На самом деле, во время компиляции код преобразовался к виду:
private static class Foo {
Object value1, value2;
...
}
...
Всё, что быдлокодер программист указал в угловых скобках, оказалось утеряно и недоступно на этапе выполнения.