Xen*_*ate 20 java generics type-erasure
如果我有课:
public class GenericClass<TBlah extends Number> {
public List<String> getList() {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试从另一个类使用该方法时:
public class OtherClass {
public void test() {
GenericClass a = null;
for (String s : a.getList()) {
}
}
}
Run Code Online (Sandbox Code Playgroud)
为什么a.getList()返回a List<Object>直到我将for循环上面的行更改为:
GenericClass<Number> a = null;
Run Code Online (Sandbox Code Playgroud)
那时a.getList()返回一个List<String>它应该做的事情?
编辑:我不明白为什么指定的合同getList()应该受到如何声明我的变量'a'的影响.getList()永远都会回归List<String>,而TBlah是什么并不重要.
c.s*_*.s. 12
因为这是泛型工作的方式.不要忘记在generics之前你宣布List它是一个列表Object.你被期望放/得Object你被迫施放以获得正确类型的对象.实际上它仍然是Object运行时的列表.
如果没有警告,泛型是编译器保证在编译时键入安全性的一种方法.在运行时没有List<String>.只有List.编译器会为您自动执行String s = list.get(i)强制转换,因此您可以在代码中编写而无需强制转换.
当你声明GenericClass a你正在声明一个原始类型时(你应该得到一个警告),因此编译器无法知道a.getList()应该返回什么类型.所以它使用Object.GenericClass<Number> a = null;现在声明编译器知道期望的类型a.getList()并使用所需的类型.
编辑:应该澄清的是,编译器只有在尊重签名合同时才能知道会发生什么(即情况就是如此GenericClass<Number>).如果您不尊重合同(即您使用的是原始类型extends Number),那么合同将不再适用.编译器的行为就像没有类型信息一样.不要忘记编译器还需要保持与在pre-generics时代创建的代码的向后兼容性