2011-06-29 22 views
10

He entrado en algo que no había encontrado antes en Java y es que necesito crear una nueva instancia de, por ejemplo, la clase ArrayList en tiempo de ejecución sin asignar un tipo conocido, entonces agregar datos a la lista. Suena un poco vago así que aquí está un ejemplo:Agregando Java a una lista genérica de tipo desconocido

Class<?> c = i.getClass(); 

Constructor<?> con = ArrayList.class.getConstructor(); 
ArrayList<?> al = (ArrayList<?>)con.newInstance(); 

al.add("something"); 

Ahora, la razón por la que estoy haciendo esto frente a sólo utilizando los genéricos se debe a que los genéricos ya están siendo utilizados en gran medida y la variable "i" en este ejemplo serían dados para usar como tipo "?". Realmente preferiría no agregar otro genérico ya que esto generaría más trabajo para el usuario y sería mucho menos flexible en el diseño final. ¿Hay alguna manera de utilizar algo como a continuación (Nota: lo que está debajo no funciona). Alguien tiene ideas?

ArrayList<c> al = (ArrayList<c>)con.newInstance(); 
+3

genéricos es para la validación en tiempo de compilación. En tiempo de ejecución, es mejor que no se preocupe por los tipos genéricos y simplemente use una 'ArrayList' no genérica. –

+0

@Bala R Tienes razón, puedo simplemente eliminar los genéricos, me preguntaba si había alguna forma de sacarlo de la clase para garantizar la validación. Gracias, tienes idea, probablemente funcione para mis propósitos. – ars265

+0

Tengo que preguntar, ¿para qué sirve una lista para la que no se conoce el tipo de datos que contendrá? – Bringer128

Respuesta

7

No se pueden agregar objetos en una Colección definida utilizando comodines genéricos. This thread podría ayudarlo.

De hecho, está creando una colección que es, sí, el tipo estupendo de cada colección, y como tal, se puede asignar a cualquier colección de genéricos; pero es demasiado genérico para permitir cualquier tipo de operación de adición ya que no hay forma de que el compilador pueda verificar el tipo de lo que está agregando. Y eso es exactamente lo que deben hacer los genéricos: verificar los tipos.

Le sugiero que lea el hilo y vea que también se aplica a lo que quiere hacer.

Su colección es simplemente demasiado genérica para permitir que se agregue cualquier cosa. El problema no tiene nada que ver con el lado derecho de la asignatura (utilizando un singleton o reflejo), está en el tipo de declaración del lado izquierdo usando comodines .

5

Si entiendo lo que quiere decir, tiene una clase C, que se desconoce en tiempo de compilación, y desea crear un ArrayList<C>, de una manera segura. Esto es posible:

Class<?> c = ...; 
ArrayList<?> al = listOf(c); 

static <T> ArrayList<T> listOf(Class<T> clazz) 
{ 
    return new ArrayList<T>(); 
} 

Esta es la teoría forma correcta de hacerlo. Pero a quién le importa. Todos sabemos sobre el borrado de tipos, y no hay posibilidad de que Java elimine el borrado de tipos y agregue el tipo de tiempo de ejecución para los parámetros de tipo. Entonces puedes usar tipos crudos y lanzar libremente, siempre y cuando sepas lo que estás haciendo.

+1

Sí, puede crear un ArrayList genérico desconocido, pero luego no puede agregarle nada, que es donde entra en juego mi pregunta. – ars265

+0

¿cómo es esto diferente de 'ArrayList al = new ArrayList ();'? – newacct

+1

@newacct presumiblemente, hay un acuerdo fuera de banda, en algún punto, la lista puede ser transferida de forma segura (por lógica de aplicación) a 'ArrayList ' y se le agrega un objeto 'X'. con borrado, ni el elenco ni el agregado son un problema. con reificación es otra historia. – irreputable

4

Puede usar ArrayList<Object>, a la que puede add() cualquier cosa.

+1

Es cierto, pero entonces son del tipo de objeto, ya no es un tipo desconocido. Esto funcionaría hasta agregar pero devuelve un Object ArrayList arrojado. El usuario entonces tendría que echar cada uno de vuelta. Ahora, Java desde 1.4, creo, retiene los datos extra de sus subclases pero no silencia lo que necesito. – ars265

+0

@ ars265: pero como no conoce el tipo en tiempo de compilación, tendrá que devolverlo de todos modos – newacct

+0

@newacct: Eso es cierto, pero estoy desarrollando un marco para que el usuario del marco haya recibido el resultado. Estaba buscando algo un poco diferente. Terminé construyendo una clase de tipo linq para el medio ambiente. – ars265

Cuestiones relacionadas