我正在阅读有关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(“ Hello”);使方法setData(Object)被执行
在类MyNode的对象上。 (继承了MyNode类
setData(Object)from Node。)
在setData(Object)的主体中,将n引用的对象的数据字段分配给String。
可以访问通过mn引用的同一对象的数据字段,并且该数据字段应为整数(因为mn是MyNode,它是一个Node。
尝试将String分配给Integer会导致Java编译器在分配时插入的强制转换导致ClassCastException。
我无法理解为什么尝试检索数据会导致异常。就我所知,不应该设置数据本身引发异常(这是在我的编译器上发生的事情,但是由于我没有使用Oracle的编译器,所以我不确定哪个是正确的)?
如果我的理解是正确的,则类MyNode应该具有两个方法:
void setData(Object); //bridge method
void setData(Integer);
因此,在Node上调用setData(Object)应该正确地调用MyNode中的bridge方法,该方法又将调用setData(Integer),该类应该在该类中引发类广播异常。但是Oracle的教程绝不是说事实并非如此。那么我的理解有什么问题呢?请帮助我理解。
最佳答案
如果我的理解是正确的,则类MyNode应该具有两个方法
void setData(Object); // bridge方法
void setData(Integer);
那是真实的。 MyNode类将具有以上两种方法。
在javap
上执行MyNode.class
也会显示它。请参阅以下两种方法,在**之间突出显示
javap MyNode.class
Compiled from "MyNode.java"
public class com.demo.generics.demo.MyNode extends com.demo.generics.demo.Node<j
ava.lang.Integer> {
public com.demo.generics.demo.MyNode(java.lang.Integer);
**public void setData(java.lang.Integer);**
public static void main(java.lang.String[]);
**public void setData(java.lang.Object);**
}
因此,在Node上调用setData(Object)应该正确地调用网桥
MyNode中的方法又调用setData(Integer),这是
应该抛出类广播异常。
这也是事实。调用它会导致以下异常:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at com.demo.generics.demo.MyNode.setData(MyNode.java:1)
at com.demo.generics.demo.MyNode.main(MyNode.java:14)
MyNode.java:14
是我打电话给n.setData("Hello");
的地方这是在我的编译器上发生的,但是由于我没有使用Oracle的编译器,所以我不确定哪个是正确的)?
这不依赖于编译器,因此应该完全相同。