por qué la siguiente conversión hacia abajo no funciona en Java:

    ArrayList<classA> aList = /*I then fill this array*/
    ArrayList<classB> bList = /* I then fill this array too*/

    /*Now put them both in the following ArrayList of Objects*/
    ArrayList<Object> myObjs =  new ArrayList<Object>();
    myObjs.add(aList);
    myObjs.add(bList);

    /*The following two lines however fails at run time*/
    ArrayList<classA> x = (ArrayList<classA>) myObjs.get(0);
    ArrayList<classB> x = (ArrayList<classB>) myObjs.get(1);

Acabo de leer de otro hilo que "se permite la reducción cuando existe la posibilidad de que tenga éxito en el tiempo de ejecución"

¿Alguien puede decirme el problema del código anterior? ¡Muchas gracias!

preguntado el 28 de julio de 12 a las 15:07

Es porque las colecciones de Java no son covariantes. UN List<Foo> no es un subtipo de List<Object>, a pesar de que Foo es un subtipo de Object. -

Si tiene una respuesta a la pregunta, probablemente debería publicarla como tal. -

3 Respuestas

Desde el Tutoriales de Java sobre genéricos:

Considere el siguiente método:

public void boxTest(Box<Number> n) { /* ... */ } 

¿Qué tipo de argumento acepta? Al observar su firma, puede ver que acepta un solo argumento cuyo tipo es Box<Number>. Pero ¿qué significa eso? ¿Se te permite pasar? Box<Integer> or Box<Double>, ¿como se podría esperar? La respuesta es "no", porque Box<Integer> y Box<Double> no son subtipos de Box<Number>.

En otras palabras: aunque classA es una subclase de Object, ArrayList<classA> is no un subtipo de ArrayList<Object>.

Respondido 28 Jul 12, 16:07

Esto es lo que significa "las colecciones de Java no son covariantes". - pelota mate

El problema es que lanzar un Object a classA no es lo mismo que lanzar ArrayList<Object>a ArrayList<classA>. Además, debe usar el nombre de la clase como parámetro de plantilla, en lugar del nombre del objeto.

Respondido 28 Jul 12, 15:07

"Además, debe usar el nombre de la clase como parámetro de plantilla, en lugar del nombre del objeto": sí, así es, cometí un error al publicar la pregunta. - LeTex

Vi que esta era una pregunta interesante. ¡He estado jugando con un código de ejemplo y esto funciona! Puede probar este código en esta increíble herramienta IDE en línea: http://ideone.com/ que compila y muestra la salida de su código en línea de forma gratuita.

import java.util.List;
import java.util.ArrayList;

class MyClass{

public static void main(String []args){

ArrayList<Integer> a = new ArrayList<Integer>();
a.add(10);
a.add(100);

ArrayList<String> b = new ArrayList<String>();
b.add("10");
b.add("100");

ArrayList<ArrayList> o = new ArrayList<ArrayList>();
o.add(a);
o.add(b);

a = o.get(0);
b= o.get(1);

System.out.println("int"+a.get(0));
System.out.println("string"+b.get(0));

System.out.println("Online IDE Works");
}

}

El problema es que tiene una ArrayList de ArrayLists. Downcasting no funciona con Objects to ArrayLists. Sin embargo, como en el código de ejemplo anterior, si proporciona el parámetro como un ArrayList en sí mismo sin proporcionar un tipo genérico para el ArrayList interno, ¡obtendrá un resultado perfecto!

Respondido 28 Jul 12, 15:07

En mi caso (si es posible), la conversión es imprescindible, porque llamaré a un método de clase A usando su objeto, que de otra manera no sería posible. - LeTex

Sí, acabo de intentarlo con a = (ArrayList )o.get(0); y b= (ListaArray )o.get(1). ¡Funciona! - afrin216

Sí, funcionará para lo que dijiste: (para descartar ArrayList a ArrayList ) y es por eso que algunos dijeron antes que "se permite el downcasting cuando existe la posibilidad de que tenga éxito en tiempo de ejecución" pero en mi caso el cast es de ArrayList a ArrayList , ahí es donde ocurre el problema: "las colecciones de Java no son covariantes", lo que a su vez sucede por el hecho de que las colecciones son mutables. - LeTex

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.