Quiero intentar desglosar la respuesta de @DerMike para explicar:
Primero, la eliminación de tipo no significa que el JDK elimine la información de tipo en tiempo de ejecución. Es un método para permitir que la verificación de tipos en tiempo de compilación y la compatibilidad de tipos en tiempo de ejecución coexistan en el mismo idioma. Como implica este bloque de código, el JDK retiene la información del tipo borrado, simplemente no está asociado con los moldes y demás cosas verificadas.
En segundo lugar, esto proporciona información de tipo genérico a una clase genérica exactamente un nivel por encima de la jerarquía del tipo concreto que se verifica, es decir, una clase padre abstracta con parámetros de tipo genérico puede encontrar los tipos concretos correspondientes a sus parámetros de tipo para una implementación concreta de sí misma que hereda directamente de eso. Si esta clase no fuera abstracta e instanciada, o la implementación concreta se redujera dos niveles, esto no funcionaría (aunque un poco de fluctuación podría hacer que se aplique a cualquier número predeterminado de niveles más allá de uno, o hasta la clase más baja con X parámetros de tipo genérico, etcétera).
De todos modos, a la explicación. Aquí está el código nuevamente, separado en líneas para facilitar la referencia:
1 # Clase genericParameter0OfThisClass =
2 # (clase)
3 # ((Tipo parametrizado)
4 # getClass ()
5 # .getGenericSuperclass ())
6 # .getActualTypeArguments () [0];
Permítanos 'ser' la clase abstracta con tipos genéricos que contiene este código. Leyendo esto más o menos al revés:
- La línea 4 obtiene la instancia de clase de clase concreta actual. Esto identifica el tipo concreto de nuestro descendiente inmediato.
- La línea 5 obtiene el supertipo de esa clase como Tipo; somos nosotros. Como somos de tipo paramétrico, podemos convertirnos en ParameterizedType (línea 3). La clave es que cuando Java determina este objeto Type, utiliza la información de tipo presente en el elemento secundario para asociar la información de tipo con nuestros parámetros de tipo en la nueva instancia de ParameterizedType. Así que ahora podemos acceder a tipos concretos para nuestros genéricos.
- La línea 6 obtiene el conjunto de tipos mapeados en nuestros genéricos, en orden según lo declarado en el código de clase. Para este ejemplo sacamos el primer parámetro. Esto vuelve como un tipo.
- La línea 2 arroja el tipo final devuelto a una clase. Esto es seguro porque sabemos qué tipos pueden tomar nuestros parámetros de tipo genérico y podemos confirmar que todos serán clases (no estoy seguro de cómo en Java se obtendría un parámetro genérico que no tenga una instancia de Clase asociado con él, en realidad).
... y eso es todo. Por lo tanto, enviamos información de tipo de nuestra propia implementación concreta a nosotros mismos y la usamos para acceder a un identificador de clase. podríamos doblar getGenericSuperclass () e ir a dos niveles, o eliminar getGenericSuperclass () y obtener valores para nosotros como un tipo concreto (advertencia: no he probado estos escenarios, todavía no se me han ocurrido).
Se vuelve complicado si tus hijos concretos están a una distancia arbitraria de saltos, o si eres concreto y no final, y especialmente complicado si esperas que alguno de tus hijos (variablemente profundos) tenga sus propios genéricos. Pero, por lo general, puede diseñar en torno a esas consideraciones, por lo que esto le ayuda en la mayor parte del camino.
¡Espero que esto haya ayudado a alguien! Reconozco que esta publicación es antigua. Probablemente recortaré esta explicación y la guardaré para otras preguntas.
Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
no estoy seguro de cuál es la restricción.java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType