0

公式ヘルプの例を考えてみましょう:

public class Node<T>{
    private 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");
        this.data=data;
    }
}
public class MyClass{
    public static void main(String[] args){
        Node n = new MyNode(5);
        n.setData(new Object());//ok
    }
}
  1. とはどういう意味Node n= new MyNode(5);ですか? Node n生の型への参照ですがNode<T>、ジェネリッククラスとして記述します。生の型はすべてNodeのジェネリック型のスーパータイプですか? raw typeへの参照を定義すると、ジェネリック型コンパイラは型チェックを行わず、型消去を開始したというのは本当ですか? のスーパータイプではないため、コンパイラがデフォルトで一致するステートメントは間違っています。Node<T>TNode nNode<T>Node<T>TObjectNode<Object>Node<Integer>

  2. コンパイラの型パラメータとは何Tですか? Node<T>コンパイラTは参照型と見なしているが、 の記述については知らないというのは本当Tですか?

4

1 に答える 1

2

1)

Node n= new MyNode(5);

MyNode オブジェクト ( のサブクラス) を指す生の (未指定の型) Node 参照がありますNode<Integer>

生の型 Node は、すべての T のジェネリック型 Node のスーパータイプですか?

ノードはのスーパークラス (スーパータイプ) ではありませんNode<T>

生の型ノード n への参照を定義すると、Node<T>ジェネリック型コンパイラは型チェックを行わず、型消去を開始したというのは本当Node<T>ですか?

コンパイラは参照のみをチェックします。参照が生の場合は、必要な型を追加できます。ジェネリックは、コンパイル時のより厳密な型チェックを提供し、ジェネリック プログラミングをサポートするために、Java 言語に導入されました。ジェネリックはコンパイラのみの問題であり、コンパイル中に型が消去 (消去) され、ジェネリックはランタイム オーバーヘッドを発生させません

Node<Object>のスーパータイプではないため、コンパイラがデフォルトで T を Object に一致させたというステートメントは間違っていますNode<Integer>

ジェネリック クラス Node の型を指定していません。これは と同等Node<Object>です。Node<Object>は のスーパークラスでNode<Integer>も と の組み合わせでもありませんNode<A>実行Node<B> 時にはすべて同じクラスです!

2) タイプ T は、使用時に指定するものです。Node クラス定義では、T は単なるプレースホルダーであるため、次の行で同じ型を使用してデータ型を指定できます。T inNode<T>は、クラスの他の場所で使用できるパラメーターと考えてください。(T は任意の変数に置き換えることができますが、E を使用するコレクションでない限り、T を使用するのが慣例です)。

次のことを検討してください...

public class MyClass extends ArrayList<Integer> {
    public static void main(String[] args) {
        ArrayList<Integer> a = new MyClass();
        a.add(new Integer(5));
        ArrayList b = a;
        b.add(new String("abc"));

        for (Integer i : a) {
            //System.out.print(i);
        }
    }
}

a は ArrayList であるため、これは問題なくコンパイルされます。

ジェネリックはコンパイラ専用であるため、コンパイルするとコードには影響しません。生の型である参照 b を使用して同じオブジェクトにエイリアスを設定できるため、他のオブジェクト (文字列など) をリストに追加できます。

ここで、整数の ArrayList として a をループしようとすると、実行時に驚いて、追加することは完全に許可されますが (すべての ArrayList はArrayList<Object>実行時にあるため)、整数にキャストすることはできません。 .

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at MyClass.main(MyClass.java:11)
于 2013-09-30T08:31:25.097 に答える