ジェネリックインスタンス作成のための型推定

ジェネリッククラスのコンストラクタの呼び出しに必要な型引数は、コンパイラがコンテキストから型引数を推定できる場合にかぎり、型パラメータの空のセット (<>) で置き換えることができます。この山括弧のペアは、非公式にダイヤモンドと呼ばれています。

たとえば、次の変数宣言を考えてみましょう。

Map<String, List<String>> myMap = new HashMap<String, List<String>>();

Java SE 7 では、コンストラクタのパラメータ化された型を、型パラメータの空のセット (<>) で置き換えることができます。

Map<String, List<String>> myMap = new HashMap<>();

ジェネリッククラスのインスタンス生成時に自動型推定を利用するには、ダイヤモンドを指定する必要があります。次の例で、HashMap() コンストラクタは Map<String, List<String>> 型ではなく raw 型 HashMap を参照しているため、コンパイラは非チェック変換警告を生成します。

Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning

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);

ジェネリッククラスおよび非ジェネリッククラスの型推定とジェネリックコンストラクタ

ジェネリッククラスと非ジェネリッククラスのどちらでも、コンストラクタをジェネリック (つまり、自身の仮型パラメータを宣言する) にできます。次に例を示します。

class MyClass<X> {
  <T> MyClass(T t) {
    // ...
  }
}

次に示すクラス MyClass のインスタンス化は、Java SE 7 およびそれ以前のリリースで有効です。

new MyClass<Integer>("")

この文は、パラメータ化された型 MyClass<Integer> のインスタンスを作成します。この文は、ジェネリッククラス MyClass<X> の仮型パラメータ X に対し、明示的に Integer 型を指定しています。このジェネリッククラスのコンストラクタには仮型パラメータ T があります。コンパイラは、このジェネリッククラスのコンストラクタの仮型パラメータ T に対して String 型を推定します (このコンストラクタの実パラメータは String オブジェクトなので)。

Java SE 7 より前のリリースのコンパイラは、ジェネリックメソッドの場合と同様に、ジェネリックコンストラクタの実型パラメータを推定できます。ただし、Java SE 7 のコンパイラは、ダイヤモンド (<>) が使用されていれば、インスタンス化されるジェネリッククラスの実型パラメータを推定できます。次の例は、Java SE 7 以降で有効です。

MyClass<Integer> myObject = new MyClass<>("");

この例では、コンパイラは、ジェネリッククラス MyClass<X> の仮型パラメータ X に対して Integer 型を推定します。このジェネリッククラスのコンストラクタの仮型パラメータ T に対しては、String 型を推定します。


Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.