1

考虑以下代码:

public class MyClass<T>{
    T data;
    public MyClass(T data){ this.data=data; }
}
public class Main{
    public static void main(String[] args){
        MyClass m= new MyClass<Integer>(3);// ok

    }
}

我阅读了“什么是原始类型,我们为什么不应该使用它? ”主题。因此,如果我们有一个参数化类型MyClass<T>,那么通过定义原始类型,我们可以MyClass m在编译时定义对原始类型的引用。MyClass此外,与给定参数化类型相对应的原始类型MyClass<T>MyClass<E> 在编译时对所有特定类型进行类型擦除之前的超类E。这个理由对吗?

4

1 回答 1

2

来自Angelika Langer 的泛型常见问题解答

原始类型是泛型类型的所有具体实例和所有通配符实例的超类型。例如,原始类型Collection是泛型类型的所有实例的超类型Collection

泛型类型层次结构

文章继续:

关于转换,允许从子类型到超类型的通常引用扩大转换。也就是说,泛型类型的每个实例化都可以转换为相应的原始类型。由于泛型和非泛型类型之间的兼容性,也允许反过来。这就是所谓的未经检查的转换,并伴有“未经检查”的警告。

要在评论中解决您的其他问题:

在原始类型的情况下:List lst= new ArrayList()编译器在做什么?有没有检查和擦除的类型?

没有通用类型检查。显然,编译器仍然确保ArrayList可分配给List. 这里没有发生任何泛型特定的事情——这样的代码通常会在泛型添加到语言之前编写。现在,它仍然允许向后兼容,但编译器会警告您使用原始类型。

为什么List lst= new ArrayList<String>()并且List<Integer> lst= new ArrayList()是正确的?

正确的是它可以成功编译,但这不是最佳实践,并且会导致编译器警告使用原始类型和未经检查的转换。

这是否意味着在类型擦除之前的编译时,原始类型是所有泛型类型的超类型和子类型?

正如泛型常见问题解答所指出的,原始类型是其所有泛型变体的超类型。允许双向赋值的原因是原始类型“选择退出”泛型类型检查,因此在赋值的任一侧使用它们隐式地执行未经检查的转换。再一次,编译器会警告你这一点,因为它威胁到类型安全。

于 2013-10-04T03:34:56.973 回答