Ответ 1
Из § 4.6 JLS (выделено мной):
Тип erasure - это отображение типов (возможно, включая параметризованные типы и переменные типа) для типов (которые никогда не являются параметризованными типами или переменными типа). Будем писать | T | для стирания типа Т. Отображение стирания определяется следующим образом:
Стирание параметризованного типа (§4.5) G является | G |.
Стирание вложенного типа T.C является | T |.C.
Стирание типа массива T [] равно | T | [].
Стирание переменной типа (§4.4) является стиранием ее левой части.
Стирание любого другого типа - это сам тип.
Следовательно, если вы объявляете класс с анонимным подклассом самого себя, он сохраняет его параметризованным типом; он не стирается. Поэтому рассмотрим следующий код:
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.HashMap;
public class Erasure<T>
{
public static void main(String...strings) {
Class<?> foo = new Erasure<HashMap<Integer, String>>() {}.getClass();
ParameterizedType t = (ParameterizedType) foo.getGenericSuperclass();
System.out.println(t.getOwnerType());
System.out.println(t.getRawType());
System.out.println(Arrays.toString(t.getActualTypeArguments()));
}
}
Выводится:
null
class Erasure
[java.util.HashMap<java.lang.Integer, java.lang.String>]
Обратите внимание, что вы получите ClassCastException
, если вы не объявили класс анонимно, из-за стирания; суперкласс не будет параметризованным типом, это будет Object
.