带有List <string>的原始类型会出现编译错误</string>

时间:2013-04-02 18:19:54

标签: java generics compiler-construction intellij-idea

我有以下Generic类:

import java.util.ArrayList;
import java.util.List;

public class GenericRaw<T> {
    public List<String> get() {
         return new ArrayList<>();
    }
}

让我们考虑一下它的用法:

public class Usage {
    public void doSomething() {
        GenericRaw base = new GenericRaw();
        for (String x : base.get()) {   }
    }
}

对于此代码,Idea不会给出任何编译错误,但Java编译器本身会:

  

java:不兼容的类型   必需:java.lang.String   发现:java.lang.Object

可在JDK 1.6.0_33以及JDK 1.7.0_17上重现。

有人可以帮我解释这个问题吗?

我的调查结果。 可以成功编译以下变体:

public void doSomething() {
    GenericRaw<?> base = new GenericRaw();
    for (String x : base.get()) {   }
}

甚至:

public void doSomething() {
    GenericRaw base = new GenericRaw();
    List<String> list = base.get();
    for (String x : list) {   }
}

1 个答案:

答案 0 :(得分:3)

  

有人可以帮我解释这个问题吗?

不确定。它遵循JLS对原始类型的描述,在section 4.8中:

  

为了便于与非泛型遗留代码接口,可以使用参数化类型(第4.5节)的擦除(第4.6节)或者元素类型为的数组类型(第10.1节)的擦除作为类型。参数化类型。这种类型称为原始类型。

GenericRaw<T>的{​​{3}}是:

public class GenericRaw {
    public List get() { ... }
}

,因为:

  

类型擦除还将构造函数或方法的签名(第8.4.2节)映射到没有参数化类型或类型变量的签名。构造函数或方法签名的擦除是一个签名,由与s相同的名称和s中给出的所有形式参数类型的擦除组成。

     

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