2011-08-08 10 views
5

Estoy intentando hacer algo que parece bastante simple: sumar los tamaños de una lista de conjuntos. Netbeans da la siguiente advertencia/error:¿Por qué Java no puede convertir una ArrayList <TreeSet <Integer>> en una lista <Set<Object>>?

actual argument java.util.ArrayList<java.util.TreeSet<java.lang.Integer>> cannot be converted to java.util.List<java.util.Set<java.lang.Object>> by method invocation conversion 

para los siguientes dos piezas de código:

/** 
* Sums the sizes of all sets in a list. Note that while there will be 
* no duplicate elements in a single set, "sister" sets may contain 
* elements, so the value returned is **not** equal to the number of unique 
* elements in all sets. 
* @param list, a List of Sets 
* @return the number of elements contained in all sets 
*/ 
public static int sizeOfListOfSets(List<Set<Object>> list) { 
    int size = 0; 

    for (Set<Object> set : list) { 
     size += set.size(); 
    } 

    return size; 
} 

y luego llamándola con lo siguiente:

ArrayList<TreeSet<Integer>> testList = new ArrayList<TreeSet<Integer>>(); 
    TreeSet<Integer>   testSet; 
    int       size = 0; 

    testSet = new TreeSet<Integer>(); 
    testSet.add(new Integer(++size)); 
    testSet.add(new Integer(++size)); 
    testList.add(testSet); 
    testSet = new TreeSet<Integer>(); 
    testSet.add(new Integer(++size)); 
    testList.add(testSet); 

    int expResult = size; 
    int result = Helpers.sizeOfListOfSets(testList); 

la última línea da error de compilación:

error: method sizeOfListOfSets in class Helpers cannot be applied to given types; 
1 error 

Entonces, ¿por qué no se puede convertir java.lang.Integer a java.lang.Object?

+1

El título propiamente pregunta sería: "¿Por qué no puede convertir un Java' ArrayList > '' en una lista > '?" –

Respuesta

14

Un List<Integer> no es un List<Object>. Si Java lo permitió, entonces puede llamar al método con List<String> y se romperá. Como señaló Jeremy Heiler puede usar List<? extends Object> y estará bien. Esto significa que se permite cualquier tipo que se extienda Object. ? se llama wildcard en jerga genérica.

+1

Sin embargo, A 'List ' es una 'Lista '. – Jeremy

+0

@Jeremy Heiler - Sí. –

+0

Usando 'Set 'conduce a' argumento real java.util.ArrayList > no se puede convertir a java.util.List > ' – MrDrews

2

Cualquier cosa se declara como un tipo genérico debe ser el exactamente el mismo tipo genérico siempre. Lo único que que puede variar es el ejemplo tipo base:

List<MyObject> myList = new ArrayList<MyObject>; 

Esto es debido, por ejemplo, si había un parámetro declarado como List<Object>, y se podía pasar un List<Integer>, entonces sería capaz de añadir cualquier tipo de objeto a esa lista, lo que rompería el tipo de seguridad.

Aunque hay una solución con el comodín ?, aún NO podrá agregar elementos a menos que lo haga así <? super MyObject>, porque cualquier cosa más alta en el árbol de herencia estaría bien para agregar a la lista.

2

El problema no es convertir de un Entero a un Objeto, sino de una lista de Entero a una lista de Objeto que falla porque List<Integer> no es un List<Object>. El compilador de Java no intenta lanzar automáticamente tipos genéricos.

Usted puede cambiar su declaración de método a algo como esto para conseguir arrastrados por el error:

public static int sizeOfListOfSets(List<Set<? extends Object>> list) 
+0

Consulte [this] (http://download.oracle.com/javase/tutorial/java/generics/subtyping.html) para obtener más información. – n0rm1e

+0

Eso todavía causaba un error, sin embargo 'public static int sizeOfListOfSets (List > list)' no. Gracias por la respuesta. – MrDrews

+0

@ houman001 - Debe ser 'List > ':) –

0

Porque eso permitirá poner cualquier objeto en esa lista. Cuando acceda a los elementos más adelante desde su referencia de lista original, contendrá objetos no enteros, aunque la lista todavía se declara como List<Integer>, lo que significa que no puede confiar en lo que dice el tipo. Ejemplo:

List<Integer> intList = new ArrayList<Integer>(); 
doSomething(intList); 
for (Integer i : intList) { 
    // i must be an Integer, so doSomething must not 
    // be able to put non-Integers into that list. 
} 
Cuestiones relacionadas