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

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

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

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, 2020, Oracle and/or its affiliates. All rights reserved.