当未指定类型参数时,为什么 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 14:51:19  来源:igfitidea点击:

Why does a Java generic raw class erase all generics to object when type parameters are unspecified?

javagenericstype-erasure

提问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 Listit was a list of Object. You were expected to put/get Objectand you were forced to cast to get your object with the correct type. Actually it still isa list of Objectin 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 ayou 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),则合同不再适用。编译器的行为就像不存在类型信息一样。不要忘记编译器还需要保持与前泛型时代创建的代码的向后兼容性