我在回顧Java泛型上的一個Oracle路徑,標題爲「Effects of Type Erasure and Bridge Methods」,並且我無法說服自己給出解釋。好奇的是,我在本地測試了這些代碼,甚至無法重現線索解釋的行爲。下面是相關代碼:甲骨文在Java泛型方面的一個潛在問題
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.
我不明白在這裏使用的演員或行爲。當我試圖運行此代碼在本地使用的IntelliJ的Java 7,我得到了這種行爲:
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;
換句話說,JVM將不允許String
與setData()
使用。這對我來說實際上很直觀,並且與我對泛型的理解一致。由於MyNode
mn
由Integer
構建,因此編譯器應將每次調用setData()
與Integer
一起投射,以確保類型安全(即傳入Integer
)。
有人可以在Oracle蹤跡中的這個明顯的錯誤?
我覺得說的頁面是它的語言鬆散的是給它太多的功勞。所以你所說的是,調用'n.setData(「Hello」)實際上是觸發編譯器生成的橋接方法,在調用super方法之前,它會將傳遞給它的每個對象都轉換爲'Integer'。那麼這解釋了我所想的一切,謝謝你的見解。 –
我傾向於嚴厲批評不良文檔,但我已經習慣於發佈可怕文檔的軍團,尤其是對於API。具有諷刺意味的是,Java在年輕時擁有一些最好的文檔。現在......我試圖讓自己對自己的輕蔑:)。 – Adam