JavaのDiamondOperatorガイド
1. 概要
この記事では、Javaのダイヤモンド演算子と、ジェネリックスとコレクションAPIがその進化にどのように影響したかを見ていきます。
2. 生のタイプ
Java 1.5より前は、CollectionsAPIはraw型のみをサポートしていました–コレクションを構築するときに型引数をパラメーター化する方法はありませんでした。
List cars = new ArrayList();
cars.add(new Object());
cars.add("car");
cars.add(new Integer(1));
これにより、任意のタイプを追加し、実行時に潜在的なキャスト例外を発生させることができました。
3. ジェネリックス
Java 1.5では、ジェネリックスが導入されました– これにより、オブジェクトを宣言および構築するときに、CollectionsAPIの引数を含むクラスの型引数をパラメーター化できます。
List<String> cars = new ArrayList<String>();
この時点で、コンストラクターでパラメーター化された型を指定する必要がありますが、これは多少判読できない場合があります。
Map<String, List<Map<String, Map<String, Integer>>>> cars
= new HashMap<String, List<Map<String, Map<String, Integer>>>>();
このアプローチの理由は、下位互換性のために raw型がまだ存在するため、コンパイラーはこれらのraw型とジェネリックを区別する必要があるためです。
List<String> generics = new ArrayList<String>();
List<String> raws = new ArrayList();
コンパイラーではコンストラクターでraw型を使用できますが、警告メッセージが表示されます。
ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized
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. 結論
簡単に言えば、diamond演算子は型推論機能をコンパイラーに追加し、ジェネリックスで導入された割り当ての冗長性を減らします。
このチュートリアルのいくつかの例は、GitHubプロジェクトのにありますので、ダウンロードして試してみてください。