问题
I called a getElements
method which returns Iterable<Element>
.
I did this:
List<Element> elements = (List<Element>) getElements();
This generates the error:
java.lang.ClassCastException: com.utesy.Element$3
cannot be cast to java.util.List
I thought a List
was a type of Iterable
?
回答1:
Yes, List<T>
extends Iterable<T>
, but that doesn't mean that you can cast from any Iterable<T>
to List<T>
- only when the value actually refers to an instance of a type of List<T>
. It's entirely possible to implement Iterable<T>
without implementing the rest of the List<T>
interface... in that case, what would you expect to happen?
To put it in simpler terms, let's change Iterable<T>
to Object
and List<T>
to String
. String
extends Object
, so you can try to cast from Object
to String
... but the cast will only succeed at execution time if the reference actually refers to a String
(or is null).
回答2:
You can turn Iterable into a List with
List<Element> elements = Lists.newArrayList( getElements() );
回答3:
List<Element>
is a type of Iterable<Element>
, but that doesn't mean that all Iterable<Element>
objects are List<Element>
objects. You can cast a List<Element>
as an Iterable<Element>
, but not the other way around.
An apple is a type of fruit, but that doesn't mean that all fruits are apples. You can cast an apple as a fruit, but not the other way around.
回答4:
why not:
Iterable<Element> i = ...; //is what you have
List<Element> myList = new LinkedList<Element>();
for (Element e:i) {
myList.add(e);
}
? needs no google lib.
回答5:
List extends Collection which in turn extends Iterable. You therefore trying to cast to a subtype which won't work unless getElements() really is returning a List (which the signature doesn't in any way guarantee).
See: http://download.oracle.com/javase/1.5.0/docs/api/java/util/List.html
回答6:
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
回答7:
From exception message it is clear that
Iterable<Element>
is not castable to List<Element>
SO you need to return List<Element>
from getElements()
回答8:
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.
回答9:
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
.
回答10:
you can try to place a guard with instanceof
:
if (AnElement instanceof AList){
//cast
AList = (AnList)Element
}
来源:https://stackoverflow.com/questions/3959892/iterableelement-cannot-be-cast-to-listelement-isnt-list-a-type-of-it