"Iterable<Element> cannot be cast to List<Element>" - Isn't `List` a type of `Iterable`?
Asked Answered
T

10

13

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?

Townscape answered 18/10, 2010 at 13:55 Comment(2)
post the code of getElements(); methodDepurative
The List interface extends the Iterable interface - so yes, List is of type Iterable, as you say. But that doesn't mean that whatever Iterable is returned by getElements is also a List. All Lists are Iterables, but not all Iterables are Lists.Arbutus
S
29

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).

Slain answered 18/10, 2010 at 14:1 Comment(0)
G
28

You can turn Iterable into a List with

List<Element> elements = Lists.newArrayList( getElements() );
Gangboard answered 12/10, 2011 at 3:49 Comment(1)
This is the most concise way to do it. Otherwise you'll need a long implementation :-( -- or just use Scala ;)Indisposition
G
18

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.

Gretchen answered 18/10, 2010 at 14:2 Comment(0)
B
5

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.

Breault answered 17/12, 2011 at 4:37 Comment(0)
F
2

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

Forzando answered 18/10, 2010 at 14:2 Comment(0)
K
1

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

Katushka answered 18/10, 2010 at 14:2 Comment(0)
C
0

Not all Iterables are Lists, 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.

Cathouse answered 18/10, 2010 at 14:0 Comment(2)
<nit-pick> "but the elements has no order, so it's not a List" - that's not the reason that a HashSet isn't a List. A HashSet isn't a List because it doesn't implement the List interface. </nit-pick>Arbutus
@Matt Ball, true... reformulated a bit... better? :)Cathouse
D
0

From exception message it is clear that Iterable<Element> is not castable to List<Element>

SO you need to return List<Element> from getElements()

Depurative answered 18/10, 2010 at 14:1 Comment(0)
E
0

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.

Ebonize answered 18/10, 2010 at 14:3 Comment(2)
List implements Iterable, and this does mean that it can be cast to it. The problem the OP is having is going the other way. This has nothing to do with it being an implement vs extend.Gretchen
Sorry, the "doesn't mean it can be cast it" was unclear, I've filled in the "it"s so it can't be wrongly interpreted as you have.Ebonize
I
0

you can try to place a guard with instanceof:

if (AnElement instanceof AList){
    //cast
    AList = (AnList)Element
}
Inject answered 17/12, 2011 at 5:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.