java - valor - Cómo obtener una instancia de clase parametrizada
pasar el valor de una variable de una clase a otra java (4)
La clase Class es una representación en tiempo de ejecución de un tipo. Dado que los tipos parametrizados sufren borrado de tipo en el tiempo de ejecución, el objeto de la clase para la clase sería el mismo que para la clase <List <Integer >> y Class <List <String >>.
La razón por la que no puede instanciarlos usando la notación .class es que esta es una sintaxis especial usada para los literales de clase. La Especificación del lenguaje Java específicamente prohíbe esta sintaxis cuando el tipo está parametrizado, por lo que List <String> .class no está permitido.
Desde que se introdujeron los genéricos, Class se parametriza, por lo que List.class produce Class <List>. Esto es claro.
Lo que no puedo descifrar es cómo obtener una instancia de Clase de tipo parametrizada en sí misma, es decir, Clase <Lista <Serie >>. Como en este fragmento:
public class GenTest {
static <T> T instantiate(Class<T> clazz) throws Exception {
return clazz.newInstance();
}
public static void main(String[] args) throws Exception {
// Is there a way to avoid waring on the line below
// without using @SuppressWarnings("unchecked")?
// ArrayList.class is Class<ArrayList>, but I would like to
// pass in Class<ArrayList<String>>
ArrayList<String> l = GenTest.instantiate(ArrayList.class);
}
}
Me encuentro con variaciones de este problema con bastante frecuencia y todavía no lo sé, si me pierdo algo, o si realmente no hay una mejor manera. Gracias por las sugerencias.
Las clases representan clases cargadas por un cargador de clases, que son tipos sin formato. Para representar un tipo parametrizado, use java.lang.reflect.ParameterizedType.
No creo que puedas hacer lo que estás intentando. En primer lugar, su método de creación de instancias no sabe que se trata de un tipo parametrizado (con la misma facilidad podría pasarlo java.util.Date.class). En segundo lugar, debido al borrado, hacer algo particularmente específico con tipos parametrizados en el tiempo de ejecución es difícil o imposible.
Si tuviera que abordar el problema de una manera diferente, hay otros pequeños trucos que puede hacer, como la inferencia de tipo:
public class GenTest
{
private static <E> List<E> createList()
{
return new ArrayList<E>();
}
public static void main(String[] args)
{
List<String> list = createList();
List<Integer> list2 = createList();
}
}
Lo único que puede hacer es crear una instancia de List<String>
directamente y llamar a su getClass()
:
instantiate(new List<String>() { ... }.getClass());
Para tipos con múltiples métodos abstractos como List
, esto es bastante incómodo. Pero desafortunadamente, llamar a los constructores de subclase (como new ArrayList<String>
) o los métodos de fábrica ( Collections.<String>emptyList()
) no funciona.