原始类型和子类型

时间:2013-10-03 05:03:38

标签: java generics subtyping

考虑以下代码:

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

    }
}

我读了“What is a raw type and why shouldn't we use it?”主题。因此,如果我们有一个参数化类型MyClass<T>,那么通过对原始类型进行defenition,我们可以在编译时将引用MyClass m定义为原始类型。此外,对应于给定参数化类型MyClass的原始类型MyClass<T>是所有特定类型MyClass<E>在类型擦除之前的编译时的E 的超类。这个理由是否正确?

1 个答案:

答案 0 :(得分:2)

来自Angelika Langer's Generics FAQ

  

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

generic type hierarchy

文章继续:

  

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

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

  

对于raw类型:List lst= new ArrayList()编译器在做什么?没有用于检查和删除的类型?

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

  

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

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

  

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

正如Generics FAQ所指出的,原始类型是其所有通用变体的超类型。两种方式允许赋值的原因是原始类型“选择退出”泛型类型检查,因此在赋值的任一侧使用它们会隐式执行未经检查的转换。再次,编译器将警告您这一点,因为它威胁到类型安全。