import java.util.*; class Test { void useIterable(Iterable i) { for (String s : i) { } for (String s : i) { } } List someStrings; void m() { useIterable(new Iterable() { final Iterator i = someStrings.iterator(); // bad @Override public Iterator iterator() { return new Iterator() { @Override public boolean hasNext() { return i.hasNext(); } @Override public String next() { return "foo " + i.next(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }); useIterable(new Iterable() { @Override public Iterator iterator() { return new Iterator() { final Iterator i = someStrings.iterator(); // ok @Override public boolean hasNext() { return i.hasNext(); } @Override public String next() { return "foo " + i.next(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }); } class Value { } class ValueIterator implements Iterator { private Value val = new Value(); @Override public boolean hasNext() { return val != null; } @Override public Value next() { Value v = val; val = null; return v; } @Override public void remove() { } } protected class ValueIterableBad implements Iterable { private ValueIterator iterator = new ValueIterator(); // bad @Override public Iterator iterator() { return iterator; } } protected class ValueIterableOk implements Iterable { @Override public Iterator iterator() { ValueIterator iterator = new ValueIterator(); // ok return iterator; } } class MyCollectionOk implements Iterable { final Iterator emptyIter = new Iterator() { // ok @Override public boolean hasNext() { return false; } @Override public Integer next() { throw new UnsupportedOperationException(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; private List ints; MyCollectionOk(List ints) { this.ints = ints; } public Iterator iterator() { if (ints.size() == 0) return emptyIter; return ints.iterator(); } } class IntIteratorBad implements Iterable, Iterator { private int[] ints; private int idx = 0; IntIteratorBad(int[] ints) { this.ints = ints; } @Override public boolean hasNext() { return idx < ints.length; } @Override public Integer next() { return ints[idx++]; } @Override public void remove() { throw new UnsupportedOperationException(); } public Iterator iterator() { return this; // bad } } class IntIteratorOk implements Iterable, Iterator { private int[] ints; private int idx = 0; private boolean returnedIterator = false; IntIteratorOk(int[] ints) { this.ints = ints; } @Override public boolean hasNext() { return idx < ints.length; } @Override public Integer next() { return ints[idx++]; } @Override public void remove() { throw new UnsupportedOperationException(); } public Iterator iterator() { // ok if (returnedIterator || idx > 0) throw new IllegalStateException(); returnedIterator = true; return this; } } class EmptyIntIterator implements Iterable, Iterator { @Override public boolean hasNext() { return false; } @Override public Integer next() { throw new UnsupportedOperationException(); } @Override public void remove() { throw new UnsupportedOperationException(); } public Iterator iterator() { // ok return this; } } }