studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones java class generics

programacion - Pasar una clase con un parámetro de tipo como parámetro de tipo para el método genérico en Java



manual de programacion android pdf (1)

Resumen del problema: me gustaría pasar una clase con un parámetro de tipo (como ArrayList<SomeClass> , por ejemplo) a un método genérico como parámetro de tipo.

Digamos que tengo un método:

public static <T> T getGenericObjectFromJson(String json, Class<T> genericType){ // details unimportant, basically returns an object of specified type return JsonParser.fromJson(json, genericType); }

Este método, por supuesto, funcionará perfectamente bien para cualquier clase de clase. Puedo llamar al método como tal, por ejemplo:

getGenericObjectFromJson(jsonString, User.class)

El problema: descubrí que no puedo hacer esto:

getGenericObjectFromJson(jsonString, ArrayList<User>.class)

Sintácticamente, esto es obviamente inválido. Sin embargo, no estoy seguro de cómo lograría algo como esto. Puedo, por supuesto, pasar ArrayList.class , sin embargo, la adición del tipo genérico hace que ya no sea sintácticamente válido, y no puedo pensar en una forma de evitarlo.

La única solución directa ha sido algo como esto (que parece bastante tonto):

getGenericObjectFromJson(jsonString, new ArrayList<User>().getClass())

Sin embargo, terminamos perdiendo el tipo genérico de todos modos, y simplemente recuperamos un ArrayList de tipo desconocido (aunque puede ser lanzado). Además, instanciando innecesariamente un objeto.

Hasta ahora, mi única solución ha sido envolver ese método en una clase que contiene un parámetro de tipo genérico que se puede instanciar de la siguiente manera:

public class JsonDeserializer<T>...

En este caso, el método getGenericObjectFromJson utilizará el tipo genérico de la clase.

La (s) Pregunta (s): En última instancia, tengo curiosidad sobre por qué no puedo aprobar una clase con un parámetro de tipo, Y si hay una manera de lograr lo que intenté hacer.

Como siempre, avíseme si hay algún problema con esta pregunta.


Esto es realmente posible en Java, usando algunos "trucos". ¡No sucumba a la presión de los fanáticos de C #! (j / k)

El "truco" es crear una clase que amplíe un tipo genérico y acceder al valor del parámetro tipo de la clase padre a través del Type devuelto por .getGenericSuperclass() o .getGenericInterfaces() .

Esto es bastante engorroso. Para simplificar nuestras vidas, Google ya ha escrito la mayor parte de la parte aburrida del código para nosotros, y la ha puesto a disposición a través de Guava.

Compruebe la clase TypeToken , que hace exactamente lo que quiere. Por ejemplo:

TypeToken<List<String>> stringListTok = new TypeToken<List<String>>() {};

Luego pasas por un TypeToken<T> lugar de un Class<T> y eso es todo. Le proporciona métodos para hacer una reflexión sobre el tipo representado por T.

Lo que esto está haciendo internamente es simplemente llamar a .getClass().getGenericSuperclass() (o ...Interfaces() ), luego algunos moldes feos de Type a ParameterizedType y recuperar toda la información de allí ( .getActualTypeArguments() , etc.).

Finalmente, si desea hacer algo similar con Dependency Injection (es decir, suponga que necesita inyectar una Class<T> en el constructor de una clase, o si desea obtener una instancia de alguna interfaz parametrizada, en la cual la instancia debería depender en el parámetro de tipo), Google Guice (un contenedor DI de Google) tiene un mecanismo muy similar para resolver el problema, llamado TypeLiteral . El uso y el código detrás de las escenas son casi idénticos a TypeToken de Guava. Verifíquelo aquí: TypeLiteral