3

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) が呼び出されます。しかし、オラクルのチュートリアルは、そうではないと言っています。では、私の理解のどこが間違っているのでしょうか? 理解を助けてください。

4

2 に答える 2