package practice;
class Node<T> {
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); }
@Override
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
}
public class Practice {
public static void main(String[] s)
{
MyNode mn = new MyNode(5);
Node n = mn; // A raw type - compiler throws an unchecked warning
n.setData("Hello"); // Causes a ClassCastException to be thrown.
Integer x = mn.data;
}
}
为什么此代码会在n.setData("Hello");
处抛出异常,而实际应该在Integer x = mn.data;
处抛出异常?
http://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html
答案 0 :(得分:2)
因为您正在尝试将String值设置为Integer变量。
答案 1 :(得分:1)
您已通过调用
为T
定义了Node
类型
MyNode mn = new MyNode(5);
即Integer
类型。通过调用n.setData("Hello");
,您尝试传入一个Integer字段的String变量。节点n
仅是Integer
类型节点mn
的参考。
答案 2 :(得分:1)
我认为教程中有一个小错误:他们应该说错误是在n.setData("Hello");
行
这是因为当您致电n.setData("Hello");
时,您调用了桥接方法:n.setData(Object object)
类上的MyNode
,否则您将遇到编译时错误。
但是桥接方法看起来像这样:
// Bridge method generated by the compiler
//
public void setData(Object data) {
setData((Integer) data);
}
您看到网桥试图在setData(Integer anInt)
上使用强制转换来调用data
。此演员表失败,因为您提供了String
。
在这个例子中,有趣的是,在使用@Override
注释时,即使技术上没有覆盖,也没有编译时错误,但编译器会在以后覆盖。这里的注释非常有用,可以告知setData(Object object)
MyNode
不会Node
上的System.out
。这解释了为什么您没有看到任何{{1}}消息。
答案 3 :(得分:0)
因为n
的类型实际上是Integer
,它是从mn
收到的。
这与List list = new ArrayList();
此处的列表实际上是ArrayList
,但仅使用List接口引用。同样,即使n
是Node
,它的实现也是MyNode
,只接受Integer
。这就是为什么你可以在String
setData()
阅读编辑示例后
该页面表示如下创建桥接方法:
class MyNode extends Node {
// Bridge method generated by the compiler
//
public void setData(Object data) {
setData((Integer) data);
}
public void setData(Integer data) {
System.out.println("MyNode.setData");
super.setData(data);
}
// ...
}
桥接方法执行以下操作
public void setData(Object data) {
setData((Integer) data);
}
这里尝试将String
“Hello”的数据转换为Integer
。因此抛出了错误。