“Iterable No se puede lanzar a la lista ” - no es `list` un tipo de` Iterable`?
-
08-10-2019 - |
Pregunta
I llama un método getElements
que devuelve Iterable<Element>
.
Hice esto:
List<Element> elements = (List<Element>) getElements();
Esto genera el error:
java.lang.ClassCastException: com.utesy.Element$3
cannot be cast to java.util.List
pensé un List
era un tipo de Iterable
?
Solución
Sí, List<T>
extiende Iterable<T>
, pero eso no quiere decir que se puede transmitir desde cualquier Iterable<T>
a List<T>
- sólo cuando el valor realmente hace referencia a una instancia de una tipo de List<T>
. Es perfectamente posible aplicar Iterable<T>
sin implementar el resto de la interfaz List<T>
... en ese caso, qué se puede esperar que suceda?
Para ponerlo en términos más simples, vamos a cambiar a Iterable<T>
Object
y List<T>
a String
. String
extiende Object
, por lo que puede intente para fundición de Object
a String
... pero el reparto solamente tendrá éxito en tiempo de ejecución si la referencia realmente se refiere a un String
(o es null).
Otros consejos
Puede activar Iterable en una lista con
List<Element> elements = Lists.newArrayList( getElements() );
List<Element>
es un tipo de Iterable<Element>
, pero eso no significa que todos los objetos son objetos Iterable<Element>
List<Element>
. Puede lanzar un List<Element>
como Iterable<Element>
, pero no al revés.
Una manzana es un tipo de fruta, pero eso no quiere decir que todas las frutas son las manzanas. Puedes lanzar una manzana como una fruta, pero no al revés.
¿por qué no:
Iterable<Element> i = ...; //is what you have
List<Element> myList = new LinkedList<Element>();
for (Element e:i) {
myList.add(e);
}
? Google no necesita lib.
Lista extiende colección que a su vez se extiende Iterable. Por lo tanto, tratando de yeso para un subtipo que no funcionará a menos getElements () realmente está devolviendo una lista (que no lo hace la firma garantiza en absoluto).
Ver: http: // download. oracle.com/javase/1.5.0/docs/api/java/util/List.html
List
es un significado subinterface de Iterable
Dicha lista incluye casi todo lo que Iterable tiene, sin embargo, no al revés. Así que no todos los métodos de una instancia de List tendrían un equivalente en Iterable.
Trate de evitar ese tipo de fundición.
Yo recomendaría que tome un rápido vistazo a la Java 6 API y los tutoriales que cubren la fundición
Desde mensaje de excepción, está claro que
Iterable<Element>
no es moldeable a List<Element>
Así que hay que volver List<Element>
de getElements()
Lista implementa la interfaz Iterable pero esto no significa Iterable puede quedar pendiente de fundición a la lista. Iterable es mucho más general y puede haber algún tipo de hash o exótica que no guarda relación con la lista. (Parece que getElements () devuelve una instancia de una clase interna anónima contenida junto getElements dentro de su clase).
Si getElements pasarían a contener listas, entonces esto sería un elenco válida. A medida que el tipo devuelto por getElements () no era en realidad una lista de lo que produce un error en tiempo de ejecución.
No todos los Iterable
s son List
s, por lo que no es seguro para echar un Iterable
arbitraria a un List
.
Tome cualquier Set
por ejemplo , un HashSet
es Iterable
pero los elementos no tiene fin, por lo que no se puede implementar la interfaz List
, y por lo tanto no es un List
.
se puede tratar de colocar un protector con instanceof
:
if (AnElement instanceof AList){
//cast
AList = (AnList)Element
}