当未指定类型参数时,为什么 Java 泛型原始类会擦除对象的所有泛型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17743406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does a Java generic raw class erase all generics to object when type parameters are unspecified?
提问by Xenoprimate
If I have a class:
如果我有一堂课:
public class GenericClass<TBlah extends Number> {
public List<String> getList() {
return null;
}
}
When I attempt to use that method from another class:
当我尝试从另一个类使用该方法时:
public class OtherClass {
public void test() {
GenericClass a = null;
for (String s : a.getList()) {
}
}
}
Why does a.getList()
return a List<Object>
until I change the line above the for loop to:
为什么a.getList()
返回 aList<Object>
直到我将 for 循环上方的行更改为:
GenericClass<Number> a = null;
At which point a.getList() returns a List<String>
like it should do?
在哪一点 a.getList() 返回一个List<String>
它应该做的?
Edit: I don't understand why the contract specified by getList()
should be affected whatsoever by how I declare my variable 'a'. getList()
always returns a List<String>
, it doesn't matter what TBlahis.
编辑:我不明白为什么指定的合同getList()
会受到我如何声明变量“a”的影响。getList()
总是返回 a List<String>
,TBlah是什么并不重要。
采纳答案by c.s.
Because this is how generics work. Do not forget that before generics when you declared a List
it was a list of Object
. You were expected to put/get Object
and you were forced to cast to get your object with the correct type. Actually it still isa list of Object
in runtime.
因为这就是泛型的工作方式。不要忘记在泛型之前声明 aList
它是一个Object
. 你应该 put/getObject
并且你被迫强制转换以获得正确类型的对象。实际上它仍然是Object
运行时的列表。
Generics is a way for the compiler to guarentee you type safety at compile timeassuming you have no warnings. In runtime there are no List<String>
. There is just List
. The compiler puts the automatic cast for you, so you are able in your code to write String s = list.get(i)
without casting.
泛型是编译器在编译时保证类型安全的一种方式,假设您没有警告。在运行时没有List<String>
. 只有List
. 编译器为您提供自动转换,因此您String s = list.get(i)
无需转换即可在代码中编写代码。
When you declare GenericClass a
you are declaring a raw type (you should get a warning on this) thus the compiler does not have a way to know what type the a.getList()
is supposed to return. So it uses Object
. When you declare GenericClass<Number> a = null;
now the compiler knows what type to expect for the a.getList()
and uses the desired one.
当你声明GenericClass a
你是在声明一个原始类型(你应该得到一个警告)因此编译器没有办法知道a.getList()
应该返回什么类型。所以它使用Object
. 当您GenericClass<Number> a = null;
现在声明时,编译器知道期望的类型a.getList()
并使用所需的类型。
Edit:It should be clarified that the compiler can know what to expect only if you respect the contract of the signature (i.e. as is the case with GenericClass<Number>
). If you don't respect the contract (i.e. you are using a raw type that does not extends Number
) then the contract does not apply anymore. The compiler behaves as if no type information was present. Do not forget that the compiler needs to also maintain backwards compatibility with code that was created in the pre-generics era
编辑:应该澄清的是,编译器只有在您尊重签名合同的情况下才能知道会发生什么(即与 的情况一样GenericClass<Number>
)。如果您不遵守合同(即您使用的是不遵守的原始类型extends Number
),则合同不再适用。编译器的行为就像不存在类型信息一样。不要忘记编译器还需要保持与前泛型时代创建的代码的向后兼容性