【发布时间】:2017-10-19 00:31:45
【问题描述】:
Java 使用类型擦除
据我了解,new ArrayList<String>() 被转换为它的原始类型,并且使用了很多语法糖来假装这个 Object 的 ArrayList 的行为就像一个 String 的 ArrayList。 Java 将此称为类型擦除。
例如
这是我用 Java 写的:
public static void main(String[] args) {
ArrayList<String> stringList = new ArrayList<>();
stringList.add("foo");
String s = stringList.get(0);
}
当我反编译字节码时,我得到了这个:
public static void main(String[] args) {
ArrayList<String> stringList = new ArrayList();
stringList.add("foo");
String s = (String)stringList.get(0);
}
因此
为什么new T[] 不能自动转换为(T[]) new Object[],使用编译器为类型擦除而提取的相同"shtick"?
请不要向我推荐这个问题:What's the reason I can't create generic array types in Java? 特别是这条评论:
问题比那个答案中指出的更深,所以进一步 需要进行调查。正如你所说,类型信息被删除并进入 编译后的代码我们在两种泛型类型之间没有区别——我们只 have 是基本类型 - 那么为什么要使用
T[]- 编译为Object[]。在这种情况下 一切都会好起来的——数组会记住它是用 对象类型,并允许保存所有类型。然而对于我来说真正的 问题是数组是协变的,这意味着Animal[]可以是 分配给Object[]。另一方面,泛型不是ArrayList<Animal>不能分配给ArrayList<Object>
因为这个逻辑是有缺陷的!
这里有两个过程。
编译器对
ArrayList<String>强制“人工”不变性。编译器将
Object转换为T。
再次,为什么不能在 Java 中使用构成所有泛型的简单语法糖来实现泛型数组,同时保持数组的正常协方差?
【问题讨论】: