Manuel
Manuel

Reputation: 2391

Why isn't a for-each loop accepting an instance of the Iterable class?

Iterable<Position<Integer>> iterable = list.positions();
    Iterator<Position<Integer>> iter = iterable.iterator();

    while (iter.hasNext()) {
        System.out.println(iter.next().getData());
    }

The above code works with no issues. list is just an instance of a List class that I wrote. It contains elements of the Integer type.

        for (Position<Integer> pos : iterable) {

    }

This code fails at the part past the colon. This should be equivalent to the first piece of code, the one with the while loop. So I don't understand why the for-each loop has an error. The error says: "Can only iterate over an array or an instance of java.lang.Iterable" - but iterable already is Iterable, isn't it? What am I missing here?

the following is the full code implementing the aforementioned methods and types.

    private class PositionIterator implements Iterator<Position<E>> {
    private Position<E> cursor = first();
    private Position<E> current = null;

    public boolean hasNext() {
        return cursor.getData() != null;
    }

    public Position<E> next() {
        if (cursor == null) throw new NoSuchElementException("reached the end of the list");
        current = cursor;
        cursor = after(cursor);
        return current;
    }
}

private class PositionIterable implements Iterable<Position<E>> {
    public Iterator<Position<E>> iterator() {
        return new PositionIterator();
    }
}

public Iterable<Position<E>> positions() {
    return new PositionIterable();
}

these are nested classes within another class called PositionalList<E>. In the interest of keeping this post compact, I decided to omit the outside class. It's just a bunch of getter and setter methods that are typical for a List class.

public interface Iterable<E> {
    public Iterator<E> iterator();
}

^that's the Iterable interface being implemented by PositionIterable

public interface Iterator<E> {
    boolean hasNext();
    E next();
}

^And that's the Iterator interface.

Upvotes: 1

Views: 99

Answers (2)

Eran
Eran

Reputation: 393986

The enhanced for loop accepts an Iterable, not an Iterator. iter is an Iterator.

Therefore :

for (Position<Integer> pos : iter)

Should be :

for (Position<Integer> pos : iterable)

EDIT : Based on the comments, your problem must be hiding java.lang.Iterable by your custom Iterable interface. If your iterable variable is of the type of your custom Iterable interface, it can't be used by the enhanced for loop, which accepts java.lang.Iterable.

Upvotes: 6

Steve Chaloner
Steve Chaloner

Reputation: 8202

You shouldn't have any issues running that code. Here's my local test code

public static void main(String[] args)
{
    Iterable<String> iterable = Arrays.asList("foo",
                                              "bar");
    for (String anIterable : iterable)
    {
        System.out.println(anIterable);
    }
}

If you have created a local class or interface called Iterable, that's the only reason I could think why this wouldn't work. If you have done that, delete it and then maybe go back and review the purpose of interfaces too.

Upvotes: 4

Related Questions