1. 概要

このクイックチュートリアルでは、単一のJava式でオブジェクトを作成および初期化するために二重中括弧を使用する方法を示します。

また、この手法がアンチパターンと見なされる理由についても説明します。

2. 標準的なアプローチ

通常、次のように一連の国を初期化して設定します。

@Test
public void whenInitializeSetWithoutDoubleBraces_containsElements() {
    Set<String> countries = new HashSet<String>();                
    countries.add("India");
    countries.add("USSR");
    countries.add("USA");
 
    assertTrue(countries.contains("India"));
}

上記の例からわかるように、次のことを行っています。

  1. HashSetのインスタンスを作成します
  2. HashSetに国を追加します
  3. 最後に、その国がHashSetに存在するかどうかを主張します

3. ダブルブレースの使用

ただし、実際には、作成と初期化を1つのステートメントで組み合わせることができます。 ここで、二重中括弧を使用します。

@Test
public void whenInitializeSetWithDoubleBraces_containsElements() {
    Set<String> countries = new HashSet<String>() {
        {
           add("India");
           add("USSR");
           add("USA");
        }
    };
 
    assertTrue(countries.contains("India"));
}

上記の例からわかるように、次のようになります。

  1. HashSetを拡張する匿名内部クラスの作成
  2. addメソッドを呼び出し、国名をHashSetに追加するインスタンス初期化ブロックを提供します。
  3. 最後に、その国がHashSetに存在するかどうかを確認できます。

4. 二重中括弧を使用する利点

二重中括弧を使用することには、いくつかの簡単な利点があります。

  • ネイティブの作成および初期化方法と比較して、コード行が少なくなります
  • コードはより読みやすい
  • 作成の初期化は同じ式で行われます

5. 二重中括弧を使用することのデメリット

二重中括弧を使用することの欠点は次のとおりです。

  • 初期化を行うためのあいまいな、広く知られていない方法
  • 使用するたびに追加のクラスが作成されます
  • 「ダイヤモンド演算子」の使用をサポートしていません–Java7で導入された機能
  • 拡張しようとしているクラスがfinalとマークされている場合は、機能しません
  • メモリリークを引き起こす可能性のある、囲んでいるインスタンスへの非表示の参照を保持します

ダブルブレースの初期化がアンチパターンと見なされるのは、これらの欠点によるものです。

6. 代替案

6.1. ストリームファクトリメソッド

代わりに、新しいJava 8 Stream APIをうまく利用して、Setを初期化できます。

@Test
public void whenInitializeUnmodifiableSetWithDoubleBrace_containsElements() {
    Set<String> countries = Stream.of("India", "USSR", "USA")
      .collect(collectingAndThen(toSet(), Collections::unmodifiableSet));
 
    assertTrue(countries.contains("India"));
}

6.2. Java9コレクションのファクトリメソッド

また、Java 9は、以下を可能にする一連の便利なファクトリメソッドを提供します。

List<String> list = List.of("India", "USSR", "USA");
Set<String> set = Set.of("India", "USSR", "USA");

このについて詳しくは、この記事をご覧ください。

7. 結論

この簡潔なチュートリアルでは、二重中括弧の使用法とその長所と短所について説明しました。

これらの例の実装は、 GitHubプロジェクトにあります。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。