Java上的类型擦除教程
我正在阅读Oracle()上的泛型跟踪,无法理解以下部分 代码片段如下所示:Java上的类型擦除教程,java,generics,type-erasure,java-bridge-method,Java,Generics,Type Erasure,Java Bridge Method,我正在阅读Oracle()上的泛型跟踪,无法理解以下部分 代码片段如下所示: 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; } } p
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.
引用同一教程-
下面是代码执行时发生的情况
- n、 setData(“你好”);导致执行方法setData(对象) 在类MyNode的对象上。(MyNode类继承了 从节点设置数据(对象)
- 在setData(Object)的主体中,n引用的对象的数据字段被分配给一个字符串李>
- 通过mn引用的同一对象的数据字段可以访问,并且应该是一个整数(因为mn是一个MyNode,它是一个节点)
- 尝试将字符串分配给整数会导致Java编译器在分配时插入的强制转换产生ClassCastException
void setData(Object); //bridge method
void setData(Integer);
因此,在节点上调用setData(Object)应该正确地调用MyNode中的bridge方法,该方法反过来调用setData(Integer),这是类强制转换异常应该抛出的位置。但是Oracle的教程特意说,情况并非如此。那么,我的理解有什么问题?请帮助我理解
如果我的理解是正确的,那么MyNode类应该有两个方法void setData(Object);//桥接方法
void setData(整数) 这是真的。MyNode类将有以上两个方法 在
MyNode.class
上执行javap
也会显示它。请参见下面突出显示的两种方法**
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);**
}
MyNode.java:14
是我调用的n.setData(“Hello”);
这是在我的编译器上发生的,但由于我没有使用Oracle的编译器,我不确定哪一个是正确的)
这不依赖于编译器,应该是相同的。我昨天在阅读文档时遇到了这个问题。我在Oracle bug tracker中打开了这个问题,并添加了这个问题作为参考。那么教程错了吗?我想他们只需要得到通知,这样他们就可以更新他们的教程了。顺便问一下,你在使用Oracle的编译器吗?@AshishDaggubatti我将浏览教程并对其进行评论。是的,我的是一个Oracle JDK。@AshishDaggubatti-hmm。我看教程在何时确切地引发
ClassCastException
这个问题上有误导性。一方面,它显示了一个ClassCastException
将在Integer x=mn.data处出现,这似乎是自相矛盾的
语句,随后在结尾表示生成的桥接方法将调用setData((整数)数据)
理想情况下,这是真正引发ClassCastException
的点。除非我们误解了教程,我怀疑:-)是的,看起来教程是错的setData
应引发运行时错误。
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);**
}
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)