我们有通用类
SomeClass<T>{ }
我们可以写下这一行:
SomeClass s= new SomeClass<String>();
没关系,因为原始类型是泛型类型的超类型。但
SomeClass<String> s= new SomeClass();
是正确的。为什么这是正确的?我认为类型擦除是在类型检查之前,但它是错误的。
使用默认编译策略调用Java编译器时,它会执行以下过程:
- 解析:读取一组* .java源文件并映射生成的令牌 顺序进入AST-Nodes。
- 输入:将定义的符号输入符号表。
- 处理注释:如果已请求,则处理在中找到的注释 指定的编译单元。
- 属性:属性语法树。此步骤包括名称 分辨率,类型检查和常数折叠。
- flow:对上一步中的树执行数据分析。 这包括检查分配和可达性。
- desugar:重写AST并翻译一些语法糖。
- 生成:生成源文件或类文件。
醇>
Generic是语法糖,因此在类型检查之后在6遍传递时调用类型擦除,在4遍传递时调用。我很困惑。
答案 0 :(得分:0)
type参数肯定参与类型检查;否则它将毫无意义(即不比原始类型更好)。
生成隐式强制转换也需要这些信息,因此它将继续存储到第7步,从技术上讲,它将作为调试符号运行。但是,只有擦除才会参与运行时类型转换检查(出于明显的向后兼容性原因)。尽管如此,如果您的通用代码可以完全静态检查,它可以像非类型擦除语言中的通用程序一样强大。
当您将SomeClass
分配给SomeClass<String>
时,编译器会向您发出有关原始类型使用的警告。此时,您的程序显然已不再安全。