Стирание типов
Стирание типов - это процесс, при котором компилятор Java
удаляет всю информацию о параметрах обобщённого типа
после проверки типов. Это означает, что во время выполнения
программы обобщённые типы не существуют - они заменяются
на свои границы или на тип Object, если границы
не указаны. Стирание типов позволяет обобщённому коду
быть совместимым с более старым кодом, который не
использовал обобщения. В первом параметре мы указываем
обобщённый тип, во втором - его границу, если она есть.
Синтаксис
// Обобщённый тип без границы стирается до Object
class Box<T>
{
private T value;
}
// Обобщённый тип с границей стирается до границы
class Box<T extends Number>
{
private T value;
}
Пример
Давайте посмотрим, как стирание типов влияет на
работу обобщённого класса. Создадим класс Box
с параметром типа T и выведем тип его поля
во время выполнения:
public class Main
{
public static void main(String[] args)
{
Box<String> box = new Box<>("abcde");
System.out.println(box.getValue().getClass().getName());
}
}
class Box<T>
{
private T value;
public Box(T value)
{
this.value = value;
}
public T getValue()
{
return value;
}
}
Результат выполнения кода:
"java.lang.String"
Несмотря на то, что во время выполнения тип T
стёрт до Object, фактический объект внутри
остаётся строкой, и его класс определяется корректно.
Пример
Давайте убедимся, что два объекта с разными параметрами типа имеют одинаковый класс после стирания типов:
public class Main
{
public static void main(String[] args)
{
Box<String> box1 = new Box<>("abcde");
Box<Integer> box2 = new Box<>(12345);
System.out.println(box1.getClass() == box2.getClass());
}
}
class Box<T>
{
private T value;
public Box(T value)
{
this.value = value;
}
public T getValue()
{
return value;
}
}
Результат выполнения кода:
true
Оба объекта имеют один и тот же класс Box,
потому что информация о параметре типа T
была стёрта во время компиляции.
Пример
Давайте посмотрим, как стирание типов работает
с границами. Если параметр типа ограничен
классом Number, то после стирания он
заменяется именно на Number, а не на
Object:
public class Main
{
public static void main(String[] args)
{
NumberBox<Integer> box = new NumberBox<>(12345);
Number value = box.getValue();
System.out.println(value);
}
}
class NumberBox<T extends Number>
{
private T value;
public NumberBox(T value)
{
this.value = value;
}
public T getValue()
{
return value;
}
}
Результат выполнения кода:
12345
Смотрите также
-
параметр типа
type-param,
который объявляет обобщённый тип -
сырой тип
raw-type,
который используется после стирания -
обобщённый метод
generic-method,
который также подвергается стиранию -
граница extends
extends-bound,
которая определяет предел стирания