我有以下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) { } }
答案 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节)也会被擦除。