2011-02-13 15 views
7

Hola ¿hay alguna manera en Java para obtener el tipo de clase staticly genéricaLa adquisición de tipo de clase genérica

he terminado con la construcción

List<TaskLocalConstraints> l = new ArrayList<TaskLocalConstraints>(); 
    Class<List<TaskLocalConstraints>> c = (Class<List<TaskLocalConstraints>>)l.getClass(); 

Me pregunto, si existe algo como:

Class c = List<TaskLocalConstraints>.class; 

(realmente no quiero construir nuevos objetos sólo para obtener su tipo)

Gracias

Respuesta

7

Puesto que todas las clases List<something> realidad corresponden a la misma clase en tiempo de ejecución, se puede hacer esto:

Class<List<TaskLocalConstraints>> c 
    = (Class<List<TaskLocalConstraints>>) List.class; 

Pero por alguna razón, Java no le gusta. Intentado con la secuencia:

Laj.java:9: inconvertible types 
found : java.lang.Class<java.util.List> 
required: java.lang.Class<java.util.List<java.lang.String>> 
Class<List<String>> c = (Class<List<String>>) List.class; 

Bueno, vamos a engañar, entonces:

Class<List<String>> c = 
    (Class<List<String>>) (Class<?>) List.class; 

Es tonto, pero funciona. Produce una advertencia de "desconexión", pero también lo hace tu ejemplo. Sin embargo, tenga en cuenta que no da como resultado la misma clase que su ejemplo. Su ejemplo devuelve la clase real del objeto, es decir, ArrayList. Esta devuelve List, obviamente.

+0

¡Señor, acaba de salvar mi día! ¡Alucinante! * inserta gif alucinante * –

0

Puede obtener la clase para List, que sería Class c = List.class. Lamentablemente en Java la información sobre los genéricos no se conserva en tiempo de ejecución, por lo que después de la compilación, su List<TaskLocalConstraints> se convertirá simplemente en List.

+0

Lo sé ... pero estoy preguntando si hay algún workaroud ... en algunos casos es posible obtener tipos genéricos incluso en tiempo de ejecución a través de la reflexión (por ejemplo, para obtener tipos genéricos que escriban la clase actual) ... – malejpavouk

+0

No creo que esto sea posible. Tiene razón en que el lenguaje no permite tales construcciones y 'Class.forName' no comprenderá la sintaxis. – Malcolm

1

No estoy seguro de si lo has notado, pero en tu ejemplo obtendrás la clase java.util.ArrayList en la variable "c". No estoy seguro si este es tu punto. Sin embargo, si nos ASUME, que sí lo es:

@SuppressWarnings("unchecked") 
Class<? extends List<TaskLocalConstraints>> c = (Class<? extends List<TaskLocalConstraints>>) ArrayList.class; 

Sin embargo, si usted necesita la lista, utilice esto:

@SuppressWarnings("unchecked") 
Class<? extends List<TaskLocalConstraints>> c = (Class<? extends List<TaskLocalConstraints>>) List.class; 

añadí @SuppressWarnings anotación para deshacerse de las advertencias. Esta anotación se puede usar con granularidad, por lo que también puede marcar su código local con ella.

La idea clave en este enfoque es que los genéricos son erasure. No hay información sobre ellos en tiempo de ejecución, las asignaciones anteriores son correctas.

+0

Este código no funciona, mira mi respuesta. Es ligeramente diferente, pero produce el mismo error de "tipos inconvertibles". –

2

Básicamente, basta con engañar al compilador. En el tiempo de ejecución es simple Class de todos modos.

un método de utilidad:

public static <C extends Collection, E, T extends Collection<E>> 
Class<T> cast(Class<C> classC, Class<E> classE) 
{ 
    return (Class<T>)classC; 
} 

Class<List<TaskLocalConstraints>> c = 
     cast(List.class, TaskLocalConstraints.class); 

Si necesita un verdadero Type completa con la información de ejecución de tipo genérico, que es una historia diferente.

+0

Impresionante. Esto realmente funciona y no es tan feo como mi solución. Me pregunto por qué funciona, sin embargo. No puedo entender por qué el compilador no produce ninguna advertencia o error para la asignación a 'c'. ¿Cómo sabe que es correcto y seguro? –

+0

La advertencia está oculta dentro de cast(). Igual que "brute cast", no es seguro, a menos que el programador se asegure de que lo haga. Por ejemplo: 'Class > c = cast (List.class, String.class)' compila y ejecuta. Pero realmente no es correcto. – irreputable

1

La solución más cercana que puedo pensar se conoce como super type tokens. Y, por supuesto, alguien lo pensó antes que yo;) Dependiendo de tu contexto, puede que la idea te resulte útil.

¡Salud!

Cuestiones relacionadas