Java类型擦除:投射插入规则?

时间:2015-04-12 08:33:09

标签: java generics casting erasure

Java tutorial on type erasure似乎没有详细说明编译器的强制转换插入的具体规则。有人可以解释导致本教程详述的转换的具体规则(转载如下):

public class Node<T> {
    public T data;

    public Node(T data) { this.data = data; }

    public void setData(T data) {
        System.out.println("Node.setData");
        this.data = data;
    }
}
public class MyNode extends Node<Integer> {
    public MyNode(Integer data) { super(data); }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(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.

具体来说,我想知道导致(MyNode)(String)插入的规则是什么。何时插入了一个强制转换,以及如何为该强制转换选择该类型?

2 个答案:

答案 0 :(得分:1)

  1. <强> MyNode mn = new MyNode(5);

    • 将创建MyNode的实例,该实例将接口T的通用类型Node定义为Integer
    • 强制转换:开发人员不需要强制转换,编译器不添加强制转换
  2. <强> Node n = (MyNode)mn;

    • 这基本上会告诉编译器忘记泛型类型T并完全使用接口Node而没有泛型会产生以下结果:想象泛型类型T到被视为java.lang.Object
    • 强制转换:开发人员不需要强制转换,编译器不添加强制转换
  3. <强> n.setData("Hello");

    • 将允许您添加任何类型的ob对象,因为T被视为对象(StringInteger,数组,其他任何内容)
    • 强制转换:开发人员不需要强制转换,编译器不添加强制转换
  4. <强> Integer x = mn.data;

    • nm.data应该返回Integer类型,因为Integer被定义为T
    • 中的泛型类型参数MyNode
    • 但是因为你使用了允许你添加String的原始类型, nm.data拥有String个实例
    • 强制转换:开发人员不需要进行强制转换,但是编译器会在幕后为您添加强制转换,并且由于类型不匹配,您将获得ClassCastException

答案 1 :(得分:1)

调用

ClassCastExceptionthrow
n.setData("Hello");

这是因为编译器构建了保持多态性的桥接方法。桥接方法如下:

 public void setData(Object data) {
       setData((Integer)data);   //the exception is thrown here
  }

由于字符串的实例无法转换为Integer,因此会抛出ClassCastException

您可以阅读有关桥梁方法的问题here