4

Javaチュートリアルで書かれたこれを読んでいるとは思えません:

はじめに、List などのジェネリック型宣言 List の呼び出しを見ました。呼び出し (通常はパラメーター化された型と呼ばれます) では、すべての仮型パラメーター (この場合は E) が実際の型引数 (この場合は Integer) に置き換えられます。

しかし、制限がない場合、正式な型パラメーターは Object に置き換えられませんか? E が Integer に置き換えられると言われているのはなぜですか?

また、ここでは、Java チュートリアルで次のように述べられています。

コード内からジェネリック Box クラスを参照するには、T を Integer などの具体的な値に置き換えるジェネリック型呼び出しを実行する必要があります。

しかし、ここでも消去のおかげで、ボックス クラスのコンパイル時 T は、Integer ではなく Object に置き換えられます。整数型は、キャスト操作用にのみ記述されます。

実際、同じチュートリアルでも次のように述べられています。

型消去プロセス中に、Java コンパイラはすべての型パラメーターを消去し、型パラメーターがバインドされている場合はそれぞれを最初のバインドに置き換え、型パラメーターがバインドされていない場合は Object に置き換えます。

私は本当に混乱しています。どれが真実ですか?またはによってT置き換えられますか?IntegerObject

4

2 に答える 2

2

あなたはさまざまなことについて話します。

チュートリアルからの引用は、タイプのインスタンス化について語っています。これは、IMHO の誤った名前の概念である型消去とは関係がなく、単純に、ジェネリック型が実行時に使用できなくなったことを意味します。

しかし、コンパイル時にはそうであり、インスタンス化はコンパイル時に行われます。

あなたの質問に答えるために、「コンパイル時」は広い意味です。以下はすべてコンパイル時に発生します。

  1. ソースファイルを読む
  2. 字句解析
  3. 解析中
  4. ...
  5. 型チェック
  6. ...
  7. コード生成

リストは決して完全ではありません。ただし、ご覧のとおり、型チェック中に、コンパイラは型のインスタンス化を認識し、それらをチェックできます。

後でバイトコードを発行しますが、バイトコードにはジェネリックを表す方法がないため、型が「消去」されます。つまり、キャストがあちこちに挿入されます。

したがって、「コンパイル時間」は何らかの形ですべてが一度に発生する瞬間であるというあなたの仮定は正しくありません。


さらに編集:

あなたはこれらすべて (つまり、「置換」という言葉) を文字通りに受け取りすぎていると思います。確かに、コンパイラには、プログラム内のすべての項目の型、名前、およびスコープが保持されるデータ構造がいくつかあります。

ほら、原則としては非常に簡単です。

static <X> List<X> meth(X[] arr) { .... }

その後、次のようにします。

Integer arr = new Integer[100];
List<Integer> list = meth(arr);
Integer foo = list.get(1);

次に、メソッドの型をインスタンス化します。

static List<Integer> meth(Integer[] arr) { .... }

ジェネリックの要点は、それmethがどのタイプでも機能すると言うことです。これは、コンパイラがチェックするものです。そして、X の配列を渡すと、すべての Xに対して、X のリストが返されることがわかります。したがって、Integer[] を渡したので、結果は である必要がList<Integer>あり、list代入は正しいです。さらに、コンパイラは、 ** すべての X ** に対して、 a から要素を取得するとList<X>、それが X になることを認識しています。

したがって、コンパイラは foo がInteger. 後でコードを生成するときに、Integer へのキャストをそこに挿入します。これは、型の消去により、List.get からの戻り値が Object であるためです。

また、「置換」は、コンパイラが何らかの方法でコードを変更することを意味するものではないことに注意してください。ジェネリック型シグネチャから(おそらく一時的に)非ジェネリック型シグネチャを作成し(置換することにより、これがより良い場合は、すべての型パラメーターを実際の型に置き換えます)、これを使用して型をチェックします。

私が言うなら、それはちょうど数学のようです: a を 42 に置き換えて、方程式が真かどうかを確認してください:

+ 1 = 43

その場合、この置換が「正確にどこで」行われるかを尋ねても意味がありません。おそらくあなたの脳の中にあります。

于 2013-11-07T15:32:27.537 に答える
1
the formal type parameter is not replaced by Object?

Object実行時のように表されるジェネリック型。<YourType>ただし、リフレクションを使用して情報を取得できます。消去は古いクラスとの互換性に関連しています。それは悪い考えでした。それについての記事

于 2013-11-07T13:46:36.390 に答える