为什么编译器将泛型类型转换为原始类型?

时间:2014-02-04 10:35:08

标签: java generics

我理解在编译时检查泛型,这样可以防止运行时异常,因为不允许首先编译带有错误泛型的代码。编译时,编译器在确认泛型已正确实现后,将泛型类型转换为原始类型。为什么?我正在尝试,但未成功地推断出这种转换的好处是什么。有没有人有解释?

3 个答案:

答案 0 :(得分:4)

因为泛型从一开始就没有成为Java的一部分(1.0)。如果是,它将使用Reification实现。引用布鲁斯·埃克尔的“用Java思考”:

  

实际上,即使程序员只编写通用代码,他们也必须处理在Java SE5之前编写的非通用库。这些图书馆的作者可能永远不会激励他们的代码,或者他们可能只是花时间去实现它。   所以Java泛型不仅必须支持向后兼容性 - 现有的代码和类文件仍然是合法的,并且继续意味着它们之前的意思 - 但也必须支持迁移兼容性,以便库可以按照自己的节奏变成通用的,并且当库时确实变得通用,它不会破坏依赖它的代码和应用程​​序。在确定这是目标之后,Java设计人员和处理该问题的各个小组决定擦除是唯一可行的解​​决方案。通过允许非通用代码与通用代码共存,Erasure可以实现向泛型的迁移。

答案 1 :(得分:0)

正如您可以阅读http://www.artima.com/intv/generics2.html Java泛型的最初目的是在未修改的VM上运行。这就是编译器处理泛型的原因。

  

Java的泛型实现基于最初名为Pizza的项目,该项目由Martin Odersky和其他人完成。 Pizza改名为GJ,然后变成了JSR,最终被Java语言采用。这个特殊的泛型提案有一个关键的设计目标,它可以在未经修改的VM [虚拟机]上运行。当然,您不必修改VM也很棒,但它也带来了一大堆奇怪的限制。限制并不一定是直接明显的,但你很快就会说,“嗯,这很奇怪。”

答案 2 :(得分:0)

您应该阅读有关类型擦除以及它如何处理原始类型的信息。 请考虑以下代码:

MyNode mn = new MyNode(5);
Node n = mn;            // A raw type - compiler throws an unchecked warning
n.setData("Hello");     // Causes a ClassCastException to be thrown.
Integer x = mn.data;

在类型擦除之后,此代码变为:

MyNode mn = new MyNode(5);
Node n = (MyNode)mn;         // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = (String)mn.data; // Causes a ClassCastException to be thrown.

以下是代码执行时发生的情况:

  • n.setData( “你好”);导致方法setData(Object)被执行 在MyNode类的对象上。 (MyNode类继承 来自Node的setData(Object)。)

  • 在setData(Object)的主体中,该对象的数据字段 由n引用的文件被分配给一个字符串。

  • 通过mn引用的同一对象的数据字段可以是 访问并期望是一个整数(因为mn是一个MyNode 是一个节点。

  • 尝试将String分配给Integer会导致ClassCastException 来自Java编译器在赋值时插入的强制转换。

您可以在此处阅读类型Erasure:http://docs.oracle.com/javase/tutorial/java/generics/erasure.html