【问题标题】:How Type Erasure work in java?类型擦除如何在 Java 中工作?
【发布时间】:2011-09-10 20:47:55
【问题描述】:

我在 http://download.oracle.com/javase/tutorial/java/generics/erasure.html 上浏览 TypeErasure 主题,上面写着 该编译器会删除与类或方法中的类型参数和类型参数相关的所有信息。

现在考虑下面的代码

public class Box<T> {
    private T t; // lineA, T stands for "Type" 

    public void add(T t) { // lineB
        this.t = t; // lineC
    }

    public T get() { // lineD
        return t; // lineE
    }
}

现在在main 方法里面我有下面的代码sn-p

Box<String> box1 = new Box<String>(); // line1
box1.add("Scott"); // line2
String s1tr=box1.get(); // line3

Box<Integer> box2 = new Box<Integer>(); // line4
box2.add(1); // line5
Integer k=box2.get(); // line6

现在在上面的代码中(在Box 类和main 方法中)编译器将进行哪些更改以及在哪一行?

正如链接所说,编译器会删除与类或方法中的类型参数和类型参数相关的所有信息,当编译器 将编译Box 类,它会分别从Box 类和main 方法中删除所有T&lt;String&gt;&lt;Integer&gt; 出现吗?如果是,删除T后的编译代码是什么?

【问题讨论】:

  • 您的示例中的第 4 行不起作用。它将触发编译器错误,因为类型(Box&lt;Integer&gt;Box&lt;String&gt;)不匹配。
  • 在大多数情况下,Type Erasure 意味着它使字节码不需要知道泛型类型(生成一些额外的代码),但是在许多方面它就像调用 Comment Erasure 一样。 ;)
  • 类型擦除不是功能,“泛型”是。类型擦除是实现泛型时的一种设计选择,用表达性换取二进制兼容性。

标签: java generics type-erasure


【解决方案1】:

类型擦除发生在编译时。 Java 编译器从源代码中删除这些泛型类型信息,并根据需要添加类型转换并提供字节码。因此生成的字节码不会包含任何关于类型参数和实参的信息。 它看起来像一个没有泛型的旧 java 代码。无法在运行时确定 T 的值,因为在编译代码之前该信息已被删除。

【讨论】:

  • 为了完整起见,代码将包含 一些 类型边界留下的信息,以及“超级类型标记”(gafter.blogspot.com/2006/12/super-type-tokens.html)。这意味着在某些相当具体的情况下,您可以恢复 T 的值。
  • 对,我想我的意思是没有“可靠”的方法来确定类型。
【解决方案2】:

在您的示例代码中没有类型限制的情况下,在 Box 类中(大致)会发生什么,方法代码中对 T 的所有引用的所有实例将被 替换目的。在使用 Box 类的代码中,&lt;String&gt;&lt;Integer&gt; 等的所有实例都将被删除

关于 Java 泛型的详尽深入的文章是 Angelika Langer's FAQ - 它还解释了类型边界的影响等等。

【讨论】:

  • 是的,同意所有的实例都会被移除,所有对T的引用都会被Object替换。但是编译器在编译完Box类之后仍然会有一些元数据信息,这样当它被其他类引用,如上面示例中的 main 方法,它应用编译时检查。对吗?
  • @Mohit:你可能是对的,类型擦除影响方法代码而不是签名。我将编辑我的答案以更正此问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
相关资源
最近更新 更多