28

ここで質問です。この最初のコード リストは問題なくコンパイルされます (JDK 1.6 | JDK 1.7)。

ArrayList<String> a = new ArrayList<String>();
String[] s = a.toArray(new String[0]);

ただし、List参照を生の型として宣言すると、次のようになります。

ArrayList a = new ArrayList();
String[] s = a.toArray(new String[0]);

String[]が必要ですが、Object[]見つかったというコンパイラ エラーが発生します。

これは、引数としてObject[]a を受け取っているにもかかわらず、コンパイラがジェネリック メソッドを返すものとして解釈していることを意味します。String[]

toArray(myArray)メソッドの署名を再確認しました。

<T> T[] toArray(T[] a);

したがって、型パラメーター<T>が List の型パラメーター (つまり ) とはまったく関係のないパラメーター化されたメソッドです<E>

ここで生の型を使用すると、独立した型パラメーターを使用してパラメーター化されたメソッドの評価にどのように影響するかわかりません。

  • このコードがコンパイルされない理由を知っている人はいますか?
  • この動作が文書化されている参照を知っている人はいますか?
4

5 に答える 5

33

これは期待どおりではありませんが、生の形式でジェネリック クラスを参照すると、インスタンス メンバーに対して何らかの方法でジェネリックを使用できなくなります。ジェネリックメソッドにも限定されません。これをチェックしてください:

 public class MyContainer<T> {

     public List<String> strings() {
         return Arrays.asList("a", "b");
     }
 }

 MyContainer container = new MyContainer<Integer>();
 List<String> strings = container.strings(); //gives unchecked warning!

これは、JLS ( 4.8 )の関連部分です。

コンストラクター (§8.8)、インスタンス メソッド (§8.4、§9.4)、または非静的フィールド (§8.3) の型 M スーパークラスまたはスーパーインターフェイスから継承されていない生の型 C は、対応する生の型です。 C に対応するジェネリック宣言での型の消去に。

于 2012-06-13T03:37:43.093 に答える
8

ジェネリックを使用しない場合、コンパイラはそれを生の型として扱うため、すべてのジェネリック型が必要になるためObject、渡すことができません 。String[]Object[]

List l = new ArrayList<String>();

生の型を使用しており、そのすべてのインスタンス メンバーが対応する消去型に置き換えられています。特に、インスタンス メソッドの宣言に現れる各パラメーター化された型は、対応する生の型に置き換えられます。詳細については、JLS 4.8 を参照してください。

于 2012-06-13T03:21:04.590 に答える
6

これは、この観察された動作を説明するために仕様で見つけた最も近い説明です。

コンストラクター (§8.8)、インスタンス メソッド (§8.8、§9.4)、または非静的フィールド (§8.3) の型 M スーパークラスまたはスーパーインターフェイスから継承されていない生の型 C は、その型の消去です生の型 C の静的メンバーの型は、C に対応するジェネリック宣言の型と同じです。

スーパークラスまたはスーパーインターフェースから継承されていない生の型の非静的型メンバーに実際の型パラメーターを渡すと、コンパイル時エラーになります。

上記と観察された動作に基づいて、すべてのジェネリック パラメーター型が raw 型から削除されたと言っても過言ではないと思います。もちろん、生の型自体の使用は、非レガシー コードでは推奨されません。

生の型の使用は、レガシー コードの互換性への譲歩としてのみ許可されています。Java プログラミング言語に汎用性が導入された後に記述されたコードで生の型を使用することは、強くお勧めできません。Java プログラミング言語の将来のバージョンでは、生の型の使用が禁止される可能性があります

于 2012-06-13T03:57:08.743 に答える
0

ArrayList はパラメーター化されていないリストであるため、型パラメーターが toArray() メソッドに渡されることはありません。それは、オブジェクトを保持していることだけを知っているだけです。a.toArray()常に Object[] 配列を返します。(String[])繰り返しますが、特定の String 型を保持することを指定する場合は、(すべての危険を含めて) にキャストする必要があります。

于 2012-06-13T03:27:22.283 に答える