の問題
List<String> list = new LinkedList();
左側ではジェネリック型を使用してList<String>
おり、右側ではロー型を使用していますLinkedList
。Javaのraw型は、実質的にはジェネリックス前のコードとの互換性のためにのみ存在し、絶対に必要でない限り、新しいコードで使用すべきではありません。
さて、Javaに最初からジェネリックがあり、ジェネリックを持つLinkedList
前に最初に作成されたような型がなかった場合、ジェネリック型のコンストラクターが左からその型パラメーターを自動的に推論するようにした可能性があります-可能であれば、割り当ての手前。しかし、そうではなく、下位互換性のためにraw型とジェネリック型を異なる方法で処理する必要があります。そのため、型パラメーターを繰り返す必要なしに、汎用オブジェクトの新しいインスタンスを宣言するわずかに異なるが、同様に便利な方法であるダイヤモンド演算子を作成する必要があります。
の元の例に関する限りList<String> list = new LinkedList()
、コンパイラーは、割り当てが必要なため、その割り当てに対して警告を生成します。このことを考慮:
List<String> strings = ... // some list that contains some strings
// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);
ジェネリックは、間違った処理を行わないようにコンパイル時に保護するために存在します。上記の例では、rawタイプを使用すると、この保護が適用されず、実行時にエラーが発生します。これが、生の型を使用してはならない理由です。
// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);
ただし、ひし形演算子を使用すると、割り当ての右側を左側と同じ型パラメーターを持つ真の総称インスタンスとして定義できます。これらのパラメーターを再度入力する必要はありません。これにより、rawタイプを使用する場合とほぼ同じ労力でジェネリックの安全性を維持できます。
理解すべき重要なことは、生の型(なし<>
)はジェネリック型と同じように扱うことができないということです。生の型を宣言すると、ジェネリックの利点と型チェックがまったく得られません。また、ジェネリックスはJava言語の汎用部分であることを覚えておく必要があります。これらは、Collection
sの引数のないコンストラクターに適用されるだけではありません。