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