“Iterable non può essere lanciato a List ” - Non è `list` un tipo di` Iterable`?
-
08-10-2019 - |
Domanda
ho chiamato un metodo che restituisce getElements
Iterable<Element>
.
Ho fatto questo:
List<Element> elements = (List<Element>) getElements();
Questo genera l'errore:
java.lang.ClassCastException: com.utesy.Element$3
cannot be cast to java.util.List
Ho pensato che una List
era un tipo di Iterable
?
Soluzione
Sì, List<T>
estende Iterable<T>
, ma questo non significa che si può lanciare da qualsiasi Iterable<T>
a List<T>
- solo quando il valore effettivamente si riferisce a un'istanza di un tipo di List<T>
. E 'del tutto possibile implementare Iterable<T>
senza implementare il resto dell'interfaccia List<T>
... in questo caso, ci si può aspettare che accada?
Per dirla in termini più semplici, cambiamo Iterable<T>
per Object
e List<T>
a String
. String
estende Object
, in modo da poter cercare per cast Object
a String
... ma il cast avrà successo solo in fase di esecuzione se il riferimento effettivamente si riferisce a un String
(o è nullo).
Altri suggerimenti
È possibile attivare Iterable in un elenco con
List<Element> elements = Lists.newArrayList( getElements() );
List<Element>
è un tipo di Iterable<Element>
, ma questo non significa che tutti gli oggetti sono oggetti Iterable<Element>
List<Element>
. È possibile lanciare un List<Element>
come Iterable<Element>
, ma non viceversa.
Una mela è un tipo di frutta, ma questo non significa che tutti i frutti sono le mele. Si può lanciare una mela come un frutto, ma non viceversa.
Perché non:
Iterable<Element> i = ...; //is what you have
List<Element> myList = new LinkedList<Element>();
for (Element e:i) {
myList.add(e);
}
? non ha bisogno di google lib.
Lista estende Collection che a sua volta si estende Iterable. È quindi cercando di fusione a un sottotipo che non funziona a meno che getElements () in realtà restituisce un elenco (che la firma non fa in alcun modo garantire).
See: http: // download. oracle.com/javase/1.5.0/docs/api/java/util/List.html
List
è un subinterface di Iterable
significato Tale elenco comprende praticamente tutto quello che Iterable ha, tuttavia, non il contrario. Quindi non tutti i metodi in un'istanza List avrebbero un equivalente in Iterable.
Cercate di evitare questo tipo di casting.
I raccomanderebbe di dare un'occhiata veloce al Java 6 API e i tutorial che coprono fusione
Da messaggio di eccezione è chiaro che
Iterable<Element>
non è calcinabile a List<Element>
Quindi è necessario tornare List<Element>
da getElements()
Elenco implementa l'interfaccia Iterable, ma questo non significa Iterable possono essere lanciati indietro alla lista. Iterable è molto più generale e può essere Hash o qualche tipo esotico che non ha alcuna relazione alla Lista. (Sembra getElements () restituisce un'istanza di una classe interna anonima contenuta fianco getElements nella sua categoria).
Se getElements non sarebbe accaduto a contenere liste allora questo sarebbe un cast valido. Come il tipo restituito da getElements () non era in realtà un elenco questo produce un errore di run-time.
Non tutti i Iterable
s sono List
s, quindi non è sicuro di lanciare un Iterable
arbitrario ad un List
.
Prendere qualsiasi Set
ad esempio , un HashSet
è Iterable
ma gli elementi senza fine, quindi non può implementare l'interfaccia List
, e non è quindi un List
.
si può provare a mettere una guardia con instanceof
:
if (AnElement instanceof AList){
//cast
AList = (AnList)Element
}