使用对通用对象的无类型引用时,对成员类型集合的迭代失败

Ale*_*lov 11 java generics

可能重复:
如果实例未分配泛型类型,则针对每个循环问题进行泛型

有人可以澄清为什么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()) {
            // ...
        }
    }


}
Run Code Online (Sandbox Code Playgroud)

编译器输出:

$ 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
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 14

当您使用原始类型(例如,Test而不是Test<T>编译器将其视为(JLS 4.8)作为该类型的擦除(JLS 4.6) - 完全擦除泛型时,它们是否使用类型参数:

如果构造函数或方法的签名被擦除,则构造函数或方法的类型参数(第8.4.4节)以及方法的返回类型(第8.4.5节)也会被擦除.

基本上,编译器会将原始类型的使用视为您不希望该代码完全了解泛型的指示 - 因此方法签名将被删除为:

public Collection getCollection()
Run Code Online (Sandbox Code Playgroud)

...因此编译时错误,因为推断的元素类型是Object,根据JLS 14.14.2.

  • 现在我理解了iterate1()和iterate3()之间的区别.但是,仍然不了解iterate1()和iterate2()之间的区别. (2认同)
  • @AlexanderPavlov:因为在`iterate2()`中,你首先将一个原始类型显式地分配给泛型类型(`Collection <String>`).这是一个未经检查的转换,但它是一个有效的转换. (2认同)