Por lo general, he visto a personas usar la clase literal así:
Class<Foo> cls = Foo.class;
Pero, ¿qué pasa si el tipo es genérico, por ejemplo, Lista? Esto funciona bien, pero tiene una advertencia ya que la lista debe ser parametrizada:
Class<List> cls = List.class
Entonces, ¿por qué no agregar un <?>
? Bueno, esto causa un error de desajuste de tipo:
Class<List<?>> cls = List.class
Pensé que algo como esto funcionaría, pero esto es solo un simple error de sintaxis:
Class<List<Foo>> cls = List<Foo>.class
¿Cómo puedo obtener una Class<List<Foo>>
estadística, por ejemplo, usando el literal de la clase?
Yo podría utilizar @SuppressWarnings("unchecked")
para deshacerse de las advertencias causadas por el uso no parametrizada de lista en el primer ejemplo, Class<List> cls = List.class
pero preferiría no hacerlo.
¿Alguna sugerencia?
List<Integer> list1 = new ArrayList<Integer>(); List<String> list2 = (List<String>)list1; list2.add("foo"); // perfectly legal
¡No puedes hacer eso en Java, obtienes un error de compilación de tipo no coincidente!List<String> list2 = (List<String>) (Object) list1;
No hay literales de clase para tipos parametrizados, sin embargo, hay objetos de tipo que definen correctamente estos tipos.
Ver java.lang.reflect.ParameterizedType - http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/ParameterizedType.html
La biblioteca Gson de Google define una clase TypeToken que permite generar simplemente tipos parametrizados y la utiliza para especificar objetos json con tipos parametrizados complejos de una manera amigable genérica. En su ejemplo, usaría:
Tenía la intención de publicar enlaces a las clases TypeToken y Gson javadoc, pero Stack Overflow no me permite publicar más de un enlace, ya que soy un usuario nuevo, puede encontrarlos fácilmente mediante la búsqueda de Google
fuente
clzz = new TypeToken<E>(){}.getRawType();
para iterar sobre enumeraciones estructuradas de manera similarclzz.getEnumConstants()
y finalmente usar refection para llamar a los métodos de miembro a laMethod method = clzz.getDeclaredMethod("getSomeFoo");
victoria! ¡Gracias!Puedes gestionarlo con un doble elenco:
@SuppressWarnings("unchecked") Class<List<Foo>> cls = (Class<List<Foo>>)(Object)List.class
fuente
Object
aClass
probablemente pueda guardar la sobrecarga de un lanzamiento de tiempo de ejecución verificado (sin sentido).Class
lugar deObject
, como sugiere, parece más significativo, pero no elimina la necesidad de la@SuppressWarnings("unchecked")
anotación, incluso agrega una nueva advertencia:Class is a raw type. References to generic type Class<T> should be parameterized
Class<?>
:(Class<List<Foo>>)(Class<?>)List.class
unchecked
advertencia. Esta respuesta no cambia / mejora nada de eso. OP incluso afirma en su pregunta que no quiere usarSuppressWarnings
...Para exponer la respuesta de cletus, en tiempo de ejecución se eliminan todos los registros de los tipos genéricos. Los genéricos se procesan solo en el compilador y se utilizan para proporcionar seguridad de tipo adicional. Realmente son solo una taquigrafía que permite al compilador insertar los tipos de letra en los lugares apropiados. Por ejemplo, anteriormente tendría que hacer lo siguiente:
se convierte
Esto permite que el compilador verifique su código en tiempo de compilación, pero en tiempo de ejecución todavía se ve como el primer ejemplo.
fuente
Las preguntas frecuentes de Java Generics y, por lo tanto, también la respuesta de cletus suena como si no tuviera sentido
Class<List<T>>
, sin embargo, el verdadero problema es que esto es extremadamente peligroso:Esto
cast()
hace que parezca seguro, pero en realidad no lo es en absoluto.Aunque no entiendo donde no puede haber
List<?>.class
=Class<List<?>>
ya que esto sería bastante útil cuando tienes un método que determina el tipo basado en el tipo genérico de unClass
argumento.Porque
getClass()
hay JDK-6184881 solicitando cambiar a usar comodines, sin embargo, no parece que este cambio se realizará (muy pronto) ya que no es compatible con el código anterior (vea este comentario ).fuente
Bueno, como todos sabemos, se borra. Pero se puede conocer en algunas circunstancias donde el tipo se menciona explícitamente en la jerarquía de clases:
Y ahora puedes hacer cosas como:
Más información aquí . Pero, de nuevo, es casi imposible recuperarlo para:
donde se borra
fuente
GenericEntity
yGenericType
.Debido al hecho expuesto de que los literales de clase no tienen información de tipo genérico, creo que debe suponer que será imposible deshacerse de todas las advertencias. En cierto modo, usar
Class<Something>
es lo mismo que usar una colección sin especificar el tipo genérico. Lo mejor que pude obtener fue:fuente
Podrías usar un método auxiliar para deshacerte de
@SuppressWarnings("unchecked")
toda una clase.Entonces podrías escribir
Otros ejemplos de uso son
Sin embargo, dado que rara vez es realmente útil, y el uso del método anula la verificación de tipo del compilador, no recomendaría implementarlo en un lugar donde sea de acceso público.
fuente