我正在浏览此页面,只是玩它提供的示例。
http://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html
我使用的是Java 8。
根据本教程页面,ClassCastException
应该在第200行抛出,但实际上它已经被抛出 - 在标记为100的行上。为什么?!教程是否过时(不适用于Java 8)?
然后我问了n
的所有方法,我可以看到方法setData(Object)
就在那里,它位于n
所指向的对象中(就是这样) - 称为桥接方法,我假设)。
好的,为什么我会在标记为100的行中获得异常?编译器是否将我的set调用转换为此n.setData((Integer)"Hello");
如果是这样,那么教程似乎确实已经过时了。
有人可以解释一下吗?
import java.lang.reflect.Method;
public class Test010 {
public static void main(String[] args) {
MyNode mn = new MyNode(5);
Node n = mn; // A raw type - compiler throws an unchecked warning
Method meth[] = n.getClass().getMethods();
n.setData("Hello"); // 100 //
System.out.println("001");
Integer x = mn.data; // 200 // // Causes a ClassCastException to be thrown.
}
}
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;
}
}
class MyNode extends Node<Integer> {
public MyNode(Integer data) {
super(data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}
答案 0 :(得分:4)
实际上在第200行抛出的异常:这不是事实,教程只是假设提到了这一点。在本教程的后面,很明显桥setData
方法包含一个强制转换为Integer
的类型。
public void setData(Object data) {
setData((Integer) data);
}
这就是导致我的问题和困惑的原因。
无论如何,这个教程页面看起来有点令人困惑,但好吧,也许只是我。
答案 1 :(得分:1)
我倾向于说教程是错的。如果没有涉及类MyNode
,或者MyNode
一般地继承Node<T>
,而不是具体地通过类型参数指定,那将是正确的。但是,一旦MyNode
定义了type参数的特定值,类型擦除就不再适用于它。
答案 2 :(得分:0)
是的,该教程使我非常困惑。以下代码中的注释并不表示jvm执行这些代码时会发生什么。
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.
只是假定Node中的setData没有被覆盖。
但是实际上bridge方法会覆盖Node中的setData,并使其似乎被MyNode中的setData覆盖。
这种情况更像是多态。