为什么 Java 泛型原始类在类型参数未指定时会擦除对象的所有泛型?

2022-09-01 23:46:17

如果我有一个类:

public class GenericClass<TBlah extends Number> {
    public List<String> getList() {
        return null;
    }
}

当我尝试从另一个类中使用该方法时:

public class OtherClass {
    public void test() {
        GenericClass a = null;
        for (String s : a.getList()) {

        }
    }
}

为什么返回 a 直到我将 for 循环上方的行更改为:a.getList()List<Object>

GenericClass<Number> a = null;

在这一点上,a.getList() 返回一个它应该做的?List<String>

编辑:我不明白为什么指定的合约应该受到我如何声明我的变量“a”的影响。 总是返回一个,TBlah是什么并不重要。getList()getList()List<String>


答案 1

因为这就是泛型的工作原理。不要忘记,在泛型之前,当您声明 a 时,它是 .你被期望放置/获取,你被迫投射以获得正确类型的对象。实际上,它仍然是运行时的列表。ListObjectObjectObject

泛型是编译器在编译时保证您键入安全的一种方式,前提是您没有警告。在运行时中没有 。只有.编译器会为您放置自动强制转换,因此您可以在代码中编写而无需强制转换。List<String>ListString s = list.get(i)

当您声明您正在声明原始类型时(您应该收到有关此的警告),因此编译器无法知道应该返回哪种类型。所以它使用.现在声明时,编译器知道期望的类型,并使用所需的类型。GenericClass aa.getList()ObjectGenericClass<Number> a = null;a.getList()

编辑:应该澄清的是,只有当您遵守签名的合同(即,在这种情况下),编译器才能知道会发生什么。如果您不尊重合同(即您使用的是不尊重的原始类型),则该合同不再适用。编译器的行为就像不存在任何类型信息一样。不要忘记,编译器还需要保持与前泛型时代创建的代码的向后兼容性GenericClass<Number>extends Number


答案 2

推荐