„Iterable kann nicht cast List sein“ - ist nicht `list` eine Art` Iterable`?
-
08-10-2019 - |
Frage
Ich rief eine getElements
Methode, die Iterable<Element>
zurück.
Ich habe diese:
List<Element> elements = (List<Element>) getElements();
Dies erzeugt den Fehler:
java.lang.ClassCastException: com.utesy.Element$3
cannot be cast to java.util.List
Ich dachte, ein List
eine Art von Iterable
ist?
Lösung
Ja, erstreckt sich List<T>
Iterable<T>
, aber das bedeutet nicht, dass Sie werfen können jeder Iterable<T>
zu List<T>
- nur dann, wenn der Wert wirklich bezieht sich auf eine Instanz eines Typ von List<T>
. Es ist durchaus möglich Iterable<T>
zu implementieren, ohne den Rest der List<T>
Schnittstelle implementiert ... in diesem Fall, was würden Sie passieren erwarten?
Um es einfacher auszudrücken: sie ändern Iterable<T>
zu Object
und List<T>
zu String
. String
erstreckt Object
, so können Sie versuchen Besetzung von Object
zu String
... aber die Besetzung wird erst zur Ausführungszeit erfolgreich sein, wenn die Referenz wirklich bezieht sich auf eine String
(oder ist null).
Andere Tipps
Sie können drehen Iterable in eine Liste mit
List<Element> elements = Lists.newArrayList( getElements() );
List<Element>
ist eine Art von Iterable<Element>
, aber das bedeutet nicht, dass alle Iterable<Element>
Objekte sind List<Element>
Objekte. Sie können eine List<Element>
als Iterable<Element>
werfen, aber nicht umgekehrt.
Ein Apfel ist eine Art von Obst, aber das bedeutet nicht, dass alle Früchte Äpfel sind. Sie können einen Apfel als Frucht gegossen, aber nicht umgekehrt.
warum nicht:
Iterable<Element> i = ...; //is what you have
List<Element> myList = new LinkedList<Element>();
for (Element e:i) {
myList.add(e);
}
? braucht keinen Google-lib.
Liste erstreckt Sammlung wiederum die Iterable erstreckt. Sie versuchen daher ein Subtyp gegossen, die funktionieren nicht, es sei denn GetElements () wirklich eine Liste zurückkehrt (die die Unterschrift in irgendeiner Weise Garantie nicht).
Siehe auch: http: // Download bereit. oracle.com/javase/1.5.0/docs/api/java/util/List.html
List
is a subinterface of Iterable
meaning that List includes pretty much everything that Iterable has, however not the other way around. So not all methods in a List instance would have an equivalent in Iterable.
Try to avoid that sort of casting.
I would recommend you to take a quick look at the Java 6 API and the tutorials covering casting
From exception message it is clear that
Iterable<Element>
is not castable to List<Element>
SO you need to return List<Element>
from getElements()
List implements the Iterable interface but this doesn't mean Iterable can be cast back to List. Iterable is much more general and may be Hash or some exotic type that bears no relation to List. (It looks like getElements() returns an instance of some anonymous inner class contained alongside getElements within its class).
If getElements would happen to contain Lists then this would be a valid cast. As the type returned by getElements() wasn't actually a List this produces a run-time error.
Not all Iterable
s are List
s, thus it's not safe to cast an arbitrary Iterable
to a List
.
Take any Set
for instance, a HashSet
is Iterable
but the elements has no order, so it can't implement the List
interface, and is thus not a List
.
you can try to place a guard with instanceof
:
if (AnElement instanceof AList){
//cast
AList = (AnList)Element
}