Итерация по типу набора элементов не выполняется при использовании нетипизированной ссылки на общий объект

Возможный дубликат:
Общие для каждой задачи цикла, если экземпляр не имеет общего типа

Может ли кто-нибудь уточнить, почему iterate1() не принимается компилятором (Java 1.6)? Я не понимаю, почему iterate2() и iterate3() намного лучше.

import java.util.Collection;
import java.util.HashSet;

public class Test<T> {

    public Collection<String> getCollection() {
        return new HashSet<String>();
    }

    public void iterate1(Test test) {
        for (String s : test.getCollection()) {
            // ...
        }
    }

    public void iterate2(Test test) {
        Collection<String> c = test.getCollection();
        for (String s : c) {
            // ...
        }
    }

    public void iterate3(Test<?> test) {
        for (String s : test.getCollection()) {
            // ...
        }
    }


}

Выход компилятора:

$ javac Test.java
Test.java:11: incompatible types
found   : java.lang.Object
required: java.lang.String
  for (String s : test.getCollection()) {
                                              ^
Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error

Ответ 1

Когда вы используете необработанный тип (например, Test, а не Test<T>), компилятор рассматривает его (JLS 4.8) как стирание (JLS 4.6) - это полностью уничтожает генерики, независимо от того, используют ли они параметр типа или нет:

Параметры типа конструктора или метода (§8.4.4) и возвращаемый тип (§8.4.5) метода также подвергаются стиранию, если подпись конструктора или метода стирается.

В принципе, использование необработанного типа обрабатывается компилятором как указание на то, что вы не хотите, чтобы этот код вообще знал о дженериках, поэтому подпись метода стирается:

public Collection getCollection()

... следовательно, ошибка времени компиляции, так как тип предполагаемого элемента Object, согласно JLS 14.14.2.