Oracle の Generics Trail ( Type Erasure ) を読んでいますが、次の部分を理解できませんでした。
コード スニペットを以下に示します。
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.
同じチュートリアルから引用 -
コードが実行されると次のようになります
- n.setData("こんにちは"); メソッド setData(Object) がクラス MyNode のオブジェクトで実行されます。(MyNode クラスは Node から setData(Object) を継承しました。)
- setData(Object) の本体では、n によって参照されるオブジェクトのデータ フィールドが String に割り当てられます。
- mn を介して参照される同じオブジェクトのデータ フィールドにアクセスでき、整数であることが期待されます (mn は Node.js である MyNode であるため)。
- String を Integer に割り当てようとすると、Java コンパイラによって割り当て時に挿入されたキャストから ClassCastException が発生します。
データを取得しようとすると例外が発生する理由がわかりません。私の理解が進む限り、データ自体を設定して例外をスローするべきではありません(これは私のコンパイラで発生しますが、Oracleのコンパイラを使用していないため、どちらが正しいかわかりません)?
私の理解が正しければ、クラス MyNode には2つのメソッドが必要です:
void setData(Object); //bridge method
void setData(Integer);
そのため、Node で setData(Object) を呼び出すと、MyNode でブリッジ メソッドが正しく呼び出され、クラスキャスト例外がスローされる場所である setData(Integer) が呼び出されます。しかし、オラクルのチュートリアルは、そうではないと言っています。では、私の理解のどこが間違っているのでしょうか? 理解を助けてください。