我正在阅读 Oracle 上的泛型跟踪(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 = mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello");
Integer x = mn.data; // Causes a ClassCastException to be thrown.
类型擦除后,此代码变为:
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 引用的对象的数据字段分配给一个 String。
- 通过 mn 引用的同一对象的数据字段可以被访问,并且应该是一个整数(因为 mn 是一个 MyNode,它是一个 Node.js。
- 尝试将 String 分配给 Integer 会导致 Java 编译器在分配时插入的强制转换引发 ClassCastException。
我无法理解为什么尝试检索数据会导致异常。据我了解,不应该设置数据本身引发异常(这是我的编译器发生的情况,但由于我没有使用 Oracle 的编译器,我不确定哪个是正确的)?
如果我的理解是正确的,那么 MyNode 类应该有两种方法:
void setData(Object); //bridge method
void setData(Integer);
因此,在 Node 上调用 setData(Object) 应该正确地调用 MyNode 中的 bridge 方法,该方法又调用 setData(Integer) ,这是应该抛出类转换异常的地方。但是甲骨文的教程特意说事实并非如此。那么我的理解有什么问题呢?请帮我理解。