Всем привет, сегодня решил немного написать про Generics, мы все используем их каждый день и при типичном выражении:


List<String> names = new ArrayList<>();
И кажется очевидным:

"У нас есть список строк, значит JVM знает, что внутри именно String".

Но это не совсем так.
В Java существует механизм, который называется стирание типов (Type Erasure).
Его смысл простой:

Информация о generic-типах существует только на этапе компиляции и удаляется перед выполнением программы.

Например:

List<String> strings = new ArrayList<>();

List<Integer> numbers = new ArrayList<>();
После компиляции для JVM это фактически:

List strings = new ArrayList();

List numbers = new ArrayList();
Для JVM оба объекта имеют один и тот же тип: ArrayList
Она не знает, что первый список был String, а второй — Integer.


Почему Java сделала именно так? - Главная причина — обратная совместимость. Generics появились только в Java 5.

До этого в коде было так:

List list = new ArrayList();
list.add("Java");
Если бы после появления Generics JVM начала хранить информацию о каждом параметре типа, старый код пришлось бы полностью менять.
Стирание типов позволило добавить Generics, не сломав существующую экосистему. 


Но из-за этого появляются ограничения.

Например:
public class Box<T> {

public T create() {
return new T();
}
}
Такой код не скомпилируется. Потому что после стирания типов JVM не знает, что такое T.
Это может быть:
String
Integer
User
Или еще один пример:

if (obj instanceof List<String>) {
...
}
Возникает тоже ошибка, так как во время выполнения JVM видит только:
obj instanceof List
Она не знает про String.

Почему тогда это работает?

List<String> list = new ArrayList<>();
String value = list.get(0);
Ведь JVM не знает про String.

Проверку делает не JVM, а компилятор и он автоматически добавляет приведение: String value = (String) list.get(0);

Именно поэтому Generics в Java — это в первую очередь механизм безопасности типов на этапе компиляции, а не runtime-механизм.

Понимание стирания типов помогает разобраться:
- почему возникает ClassCastException;
- почему появляются bridge methods;
- почему нельзя создать массив new T[];
- почему возникают ошибки InvalidTypesException в некоторых фреймворках.
Просмотры: 91
Открыть в MAX Сообщить о неточности

Репосты публикации

Публикация канала

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти