Я хочу попытаться объяснить ответ @DerMike, чтобы объяснить:
Во-первых, удаление типа не означает, что JDK удаляет информацию о типе во время выполнения. Это метод, позволяющий проверять типы во время компиляции и совместимости типов во время выполнения на одном языке. Как следует из этого блока кода, JDK сохраняет стертую информацию о типе - она просто не связана с проверенными приведениями и прочим.
Во-вторых, это предоставляет информацию общего типа для универсального класса ровно на один уровень выше иерархии от проверяемого конкретного типа, т.е. абстрактный родительский класс с параметрами универсального типа может найти конкретные типы, соответствующие параметрам его типа, для конкретной конкретной реализации, которую непосредственно наследует от него. Если бы этот класс был неабстрактным и реализованным, или конкретная реализация была на два уровня ниже, это не сработало бы (хотя небольшое колебание могло бы сделать его применимым к любому заранее определенному количеству уровней, превышающему один, или вплоть до самого низкого класса с параметрами универсального типа X и т. д.).
Во всяком случае, к объяснению. Вот снова код, разделенный на строки для удобства:
1# Class genericParameter0OfThisClass =
2# (Class)
3# ((ParameterizedType)
4# getClass()
5# .getGenericSuperclass())
6# .getActualTypeArguments()[0];
Пусть 'us' будет абстрактным классом с универсальными типами, который содержит этот код. Читая это примерно наизнанку:
- Строка 4 получает текущий конкретный класс 'Экземпляр класса. Это идентифицирует конкретный тип нашего непосредственного потомка.
- Строка 5 получает супертип этого класса как Тип; это мы. Поскольку мы параметрический тип, мы можем безопасно привести себя к ParameterizedType (строка 3). Ключ в том, что когда Java определяет этот объект Type, она использует информацию о типе, присутствующую в дочернем элементе, чтобы связать информацию о типе с нашими параметрами типа в новом экземпляре ParameterizedType. Так что теперь мы можем получить доступ к конкретным типам наших дженериков.
- Строка 6 получает массив типов, сопоставленных с нашими обобщениями, в порядке, объявленном в коде класса. Для этого примера мы вытащим первый параметр. Это возвращается как Тип.
- В строке 2 приведен окончательный тип, возвращаемый классу. Это безопасно, потому что мы знаем, какие типы могут принимать параметры универсального типа, и можем подтвердить, что все они будут классами (я не уверен, как в Java можно было бы получить универсальный параметр, у которого нет экземпляра класса связано с этим, собственно).
... и это все. Поэтому мы помещаем информацию о типе из нашей собственной конкретной реализации обратно в себя и используем ее для доступа к дескриптору класса. мы могли бы удвоить getGenericSuperclass () и пройти два уровня или исключить getGenericSuperclass () и получить значения для себя как конкретный тип (предостережение: я не тестировал эти сценарии, они еще не подошли для меня).
Становится сложно, если ваши конкретные дети находятся на произвольном количестве прыжков, или если вы конкретны и не окончательны, и особенно сложно, если вы ожидаете, что у любого из ваших (переменно глубоких) детей будут свои собственные дженерики. Но обычно вы можете придумать эти соображения, так что вы получите большую часть пути.
Надеюсь, это помогло кому-то! Я признаю этот пост древним. Я, вероятно, отрежу это объяснение и оставлю его для других вопросов.