Итерация по типу набора элементов не выполняется при использовании нетипизированной ссылки на общий объект
Возможный дубликат:
Общие для каждой задачи цикла, если экземпляр не имеет общего типа
Может ли кто-нибудь уточнить, почему 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.