JavaのDiamondオペレータの手引き

1概要

この記事では、Javaの diamond演算子、および generics とCollections APIがその進化にどのような影響を与えたかについて説明します

2生の種類

  • Java 1.5より前では、コレクションAPIは生の型のみをサポートしていました - コレクションを構築するときに型引数をパラメータ化する方法はありませんでした。

List cars = new ArrayList();
cars.add(new Object());
cars.add("car");
cars.add(new Integer(1));

これにより、任意の型を追加することができ、実行時に例外が発生する可能性がありました。

3ジェネリックス

Java 1.5では、Genericsが導入されました。 これにより、オブジェクトの宣言および構築時に、クラスの型引数をコレクション化APIの引数も含めてパラメータ化できました

List<String> cars = new ArrayList<String>();

この時点で、コンストラクタでパラメータ化された型を指定する必要があります。

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

このアプローチの理由は、後方互換性のために生の型がまだ存在しているためです。そのため、コンパイラは生の型と総称を区別する必要があります。

List<String> generics = new ArrayList<String>();
List<String> raws = new ArrayList();

コンパイラはまだコンストラクタで生の型を使用することを許可していますが、警告メッセージが表示されます。

…… ArrayListは生の型です。ジェネリック型ArrayList <E>への参照はパラメータ化する必要があります ……

4ダイヤモンドオペレーター

Java 1.7で導入されたダイアモンド演算子 - 型推論を追加し、代入の冗長性を減らします - 総称を使用する場合

List<String> cars = new ArrayList<>();

Java 1.7コンパイラの型推論機能 は、呼び出し に一致する最適なコンストラクタ宣言** を決定します。

車両とエンジンを操作するために、次のインターフェースとクラス階層を検討します。

public interface Engine { }
public class Diesel implements Engine { }
public interface Vehicle<T extends Engine> { }
public class Car<T extends Engine> implements Vehicle<T> { }

菱形演算子を使用して Car の新しいインスタンスを作成しましょう。

Car<Diesel> myCar = new Car<>();

内部的には、コンパイラは Diesel Engine インタフェースを実装していることを認識しているので、型を推測することによって適切なコンストラクタを決定できます。

5結論

簡単に言うと、ひし形演算子は型推論機能をコンパイラに追加し、総称で導入された割り当ての冗長性を減らします。

このチュートリアルの例はhttps://github.com/eugenp/tutorials/tree/master/core-java-lang-syntax[GitHubプロジェクト]にあります。