Jou*_*wee 7 java generics type-erasure
因此,当使用具有List(或Map或Set等)作为属性的泛型类时,我遇到了一个奇怪的编译错误.
尝试迭代(使用foreach)List时发生编译错误:
Sample.java:11: error: incompatible types
for (String string : s.getStringList()) {
required: String
found: Object
Run Code Online (Sandbox Code Playgroud)
为了清楚起见,我知道这个问题有一个简单的解决方法,但我想了解代码有什么问题
以下是我创建的示例:
import java.util.List;
public class Sample<T> {
public List<String> stringList;
public static void main(String[] args) {
Sample s = new Sample();
// Why this doesn't work?
for (String string : s.getStringList()) {
}
// Why does both of the following work?
List<String> newList = s.getStringList();
Sample<Object> s2 = new Sample<>();
for (String string : s2.getStringList()) {
}
}
public List<String> getStringList() {
return stringList;
}
}
Run Code Online (Sandbox Code Playgroud)
这些线
Sample s = new Sample();
// Why this doesn't work?
for (String string : s.getStringList()) {
}
Run Code Online (Sandbox Code Playgroud)
因为你正在使用类的原始形式而无法工作Sample.当你使用类的原始形式时,类中的所有泛型,甚至是不相关的泛型,都会执行类型擦除.这意味着,getStringList现在只是返回List的ObjectS,不是List<String>的String秒.
这部分Java是在Java 1.5中与Generics一起引入的,因此现在使用泛型的旧版本的版本将向后兼容.这样,迭代的东西,List以前必须使用Object,仍然可以使用Object原始形式List.
在JLS,第4.8节涉及原始类型:
更准确地说,原始类型被定义为以下之一:
- 通过获取泛型类型声明的名称而不带伴随类型参数列表而形成的引用类型.
和
未从其超类或超接口继承的原始类型C的构造函数(第8.8节),实例方法(第8.4节,第9.4节)或非静态字段(第8.3节)M的类型是对应的原始类型到它的类型的擦除对应于下在的一般声明
(强调我的)
理由:
原始类型的使用仅允许作为遗留代码兼容性的让步.在将泛型引入Java编程语言之后编写的代码中使用原始类型是非常不鼓励的.未来版本的Java编程语言可能会禁止使用原始类型.