[英]generic type erasure ClassCastException
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");
拋出異常n.setData("Hello");
實際上它應該在Integer x = mn.data;
拋出異常Integer x = mn.data;
?
http://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html
因為您正在嘗試將String值設置為Integer變量。
您已經通過調用為Node
定義了類型T
MyNode mn = new MyNode(5);
即Integer
類型。 通過調用n.setData("Hello");
您正在嘗試為Integer字段傳遞String變量。 節點n
僅僅是Integer
類型節點mn
的參考。
我認為教程中有一個小錯誤:他們應該說錯誤是在n.setData("Hello");
行n.setData("Hello");
那是因為當你調用n.setData("Hello");
你在MyNode
類上調用bridge方法: n.setData(Object object)
,否則會產生編譯時錯誤。
但是橋接方法看起來像這樣:
// Bridge method generated by the compiler
//
public void setData(Object data) {
setData((Integer) data);
}
您會看到網橋嘗試使用對data
setData(Integer anInt)
來調用setData(Integer anInt)
。 此演員表失敗,因為您提供了一個String
。
在這個例子中有趣的是,使用@Override
注釋時沒有編譯時錯誤,即使您在技術上沒有覆蓋,但編譯器稍后會覆蓋。 注釋在這里非常有用,以告知將在MyNode
上調用setData(Object object)
而不是在Node
上調用。 這解釋了為什么您沒有看到任何System.out
消息。
因為n
的類型實際上是從mn
收到的Integer
。
它與List list = new ArrayList();
原理相同List list = new ArrayList();
這里的列表實際上是一個ArrayList
,但只使用List接口引用。 同樣,即使n
是一個Node
,它的實現也是一個只接受Integer
的MyNode
。 這就是你可以在setData()
放置一個String
的原因
閱讀編輯示例后
該頁面表示如下創建橋接方法:
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
。 因此拋出了錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.