Hi,
I'm wondering how to iterate over a List with mixed contents using foreach. See the example code below.
public class GenericsForeach {
class A {
void methodA() {
System.out.println(getClass().getSimpleName() + ": A");
}
}
class B extends A {
void methodB() {
System.out.println(getClass().getSimpleName() + ": B");
}
}
void test() {
List<A> listOfA = new ArrayList<A>();
listOfA.add(new A());
List<B> listOfB = new ArrayList<B>();
listOfB.add(new B());
List<? super A> mixed = new ArrayList<A>();
mixed.addAll(listOfA);
mixed.addAll(listOfB);
Iterator<? super A> it = mixed.iterator();
while (it.hasNext()) {
A item = (A) it.next();
item.methodA();
}
// XXX: this does not work
// for (A item : mixed) {
// item.methodA();
// }
}
public static void main(String[] args) {
new GenericsForeach().test();
}
}
I construct two lists with different, but related, content types A
and B
(B
extends A
). I add the two lists to a 'mixed' list, which I declare to contain <? super A>
types. Since this mixed list is 'consuming' items of type A
(or B
) I applied Bloch's PECS rule (Producer Extends, Consumer Super) to determine that I need <? super A>
here.
So far, so good. But now when I want to iterate over this mixed list, I can only seem to do it with an Iterator<? super A>
, and a cast A item = (A) it.next()
. When I try to use a foreach loop (see commented-out code), no joy:
Type mismatch: cannot convert from element type capture#8-of ? super GenericsForeach.A to GenericsForeach.A
Eclipse even helpfully offers to
Change type of 'item' to '? super A'
but this results in disaster:
for (? super A item : mixed) {
item.methodA();
}
So I don't know. Eclipse doesn't seem to know. Does anybody else here know if this is possible, and if it's not, why not?