Мне интересно, как перебирать список со смешанным содержимым, используя foreach. Смотрите пример кода ниже.
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();
}
}
Я создаю два списка с разными, но связанными типами контента A
и B
(B
extends A
). Я добавляю два списка в «смешанный» список, который, как я заявляю, содержит <? super A>
типов. Поскольку этот смешанный список «потребляет» элементы типа A
(или B
), я применил правило PECS Блоха (Producer Extends, Consumer Super), чтобы определить, что мне нужно <? super A>
здесь.
Пока все хорошо. Но теперь, когда я хочу перебрать этот смешанный список, я могу только сделать это с Iterator<? super A>
и приведением A item = (A) it.next()
. Когда я пытаюсь использовать цикл foreach (см. Закомментированный код), радости нет:
Несоответствие типов: невозможно преобразовать из захвата типа элемента # 8-of? супер GenericsForeach.A для GenericsForeach.A
Затмение даже услужливо предлагает
Изменить тип элемента 'на'? супер A '
но это приводит к катастрофе:
for (? super A item : mixed) {
item.methodA();
}
Так что я не знаю. Затмение, похоже, не знает. Кто-нибудь еще здесь знает, возможно ли это, а если нет, то почему бы и нет?