11

Generics tutorial のこの例を考えてみましょう。

List<String> list = new ArrayList<>();
list.add("A");

// The following statement should fail since addAll expects
// Collection<? extends String>

list.addAll(new ArrayList<>());

コンパイルする必要があるように見えるのに、最後の行がコンパイルされないのはなぜですか。最初の行は非常によく似た構成を使用しており、問題なくコンパイルされます。

くわしく説明してください。

4

3 に答える 3

14

まず第一に: Java 7 を使用していない限り、ダイヤモンド<>はその Java バージョンでのみ導入されているため、これはすべて機能しません。

また、この回答は、読者がジェネリックの基本を理解していることを前提としています。そうでない場合は、チュートリアルの他の部分を読み、それらを理解してから戻ってきてください。

ひし形は、実際には、コンパイラが独自に型を見つけることができる場合に、ジェネリック型情報を繰り返す必要がないためのショートカットです。

最も一般的な使用例は、変数が初期化された同じ行で定義されている場合です。

List<String> list = new ArrayList<>(); // is a shortcut for
List<String> list = new ArrayList<String>();

この例では大きな違いはありませんが、一度理解すれば大きな機能強化にMap<String, ThreadLocal<Collection<Map<String,String>>>>なります(注:このような構造を実際に使用することはお勧めしません!)。

問題は、ルールがそこまでしか進んでいないことです。上記の例では、どのタイプを使用する必要があるかは明らかであり、コンパイラと開発者の両方が同意しています。

この行で:

list.addAll(new ArrayList<>());

明らかなようです。少なくとも開発者は、型が であるべきであることを知っていますString

ただし、 の定義Collection.addAll()を見ると、パラメーターの型が であることがわかりますCollection<? extends E>

これは、addAllが の型を拡張する未知の型のオブジェクトを含むコレクションを受け入れることを意味しますlistaddAllこれはaList<Integer>を aに変換できることを意味するので良いのですがList<Number>、型の推論が難しくなります。

実際、JLS によって現在レイアウトされている規則内では、型推論が機能しなくなります。状況によっては、ルールを拡張して機能させることができると主張することもできます、現在のルールはそれを行わないことを暗示しています。

于 2011-09-26T13:49:33.590 に答える
1

型推論のドキュメントからの説明は、この質問に直接答えているようです (他に何かが欠けていない限り)。

Java SE 7 以降では、ジェネリック インスタンスの作成に対して制限付きの型推論がサポートされています。コンストラクターのパラメーター化された型がコンテキストから明らかな場合にのみ、型の推定を使用できます。たとえば、次の例はコンパイルされません。

List<String> list = new ArrayList<>();
list.add("A");

  // The following statement should fail since addAll expects
  // Collection<? extends String>

list.addAll(new ArrayList<>());

ひし形はメソッド呼び出しで機能することが多いことに注意してください。ただし、より明確にするために、主にひし形を使用して、宣言されている変数を初期化することをお勧めします

比較すると、次の例はコンパイルされます。

// The following statements compile:

List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);
于 2011-09-26T13:48:33.400 に答える
0

メソッド呼び出しをコンパイルするとき、javac は、どのメソッド シグネチャがそれらに一致するかを判断する前に、最初に引数の型を知る必要があります。したがって、メソッドのパラメーターの型は、引数の型が判明する前にわかりません。

これは改善できるかもしれません。現在、引数の型はコンテキストに依存しません。

于 2011-09-26T20:58:32.970 に答える