Java类型擦除:转换插入规则?

Java Type Erasure: Rules of cast insertion?

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)。什么时候插入演员表,如何选择演员表的类型?

  1. MyNode mn = new MyNode(5);

    • 将创建一个 MyNode 的实例,它将接口 Node 的通用类型 T 定义为 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 应该 return 一个 Integer 类型,因为 IntegerMyNode [=91] 中定义为通用类型参数 T =]
    • 但是因为您使用了允许您添加 String 的原始类型,所以 nm.data 包含一个 String 实例
    • 转换:开发人员不需要转换,但是编译器会在幕后为您添加转换为 Integer 并且由于类型不匹配,您将得到 ClassCastException

当调用

时,ClassCastException 将是 throw
n.setData("Hello");

这是因为编译器构建桥接方法来保留多态性。桥接方法如下所示:

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

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

您可以阅读桥接方法 here