2009-09-03 10 views
41

{{ ... }}次のコードでブロックの意味は何ですか?新しいクラス(...)の意味{{...}}初期化イディオム

class X { 

    private Y var1; 

    private X() { 
     Z context = new Z(new SystemThreadPool()) {{ 
      var1 = new Y(); 
     }}; 
    } 

} 
+5

私はそれは二重の中括弧のためにGoogleに簡単ではありませんね。 –

+3

@Tom Hawtin:あなたはGoogleの代わりに "double brace"を使うことができます... –

答えて

62

それはdouble curly brace initializationと呼ばれています。 (編集:リンクが削除されました、archived here

これは、匿名サブクラスを作成していることを意味し、二重括弧内のコードは基本的にコンストラクタです。基本的にコレクション定数であるものを作成するためのJavaの構文はやや厄介なので、コレクションにコンテンツを追加することがよくあります。

だから、あなたが行う可能性があります:

List<String> list = new ArrayList<String>() {{ 
    add("one"); 
    add("two"); 
    add("three"); 
}}; 

の代わり:

List<String> list = new ArrayList<String>(); 
list.add("one"); 
list.add("two"); 
list.add("three"); 

を私は実際にそのようにしないと、これを行うことを好む:

List<String> list = Arrays.asList("one", "two", "three"); 

だから、それはdoesnのそのような場合には、便利なヘルパーを持たないマップ、例えば、マップに対しては意味をなさない。

+0

@skaffmanこれは、[JATL](http://code.google.com/p/jatl)のような "fluid java"試み。 –

+6

Arrays.asList()は、機能が制限されているjava.util.ArrayListではなくjava.util.Arrays.ArrayList.ArrayListを返します。 – Asaf

+3

このテクニックは難解で、いくつかの注意点があります。何らかの正当な理由がなくても、壊れたequals()契約やメモリ使用量が増加する可能性があります。あなたがしていることを正確に知っていなければ、二重ブレースの初期化を避けるほうがよいでしょう。詳細については、[こちら](http://www.ayp-sd.blogspot.com/2012/12/double-brace-initialization-in-java.html)の記事をご覧ください。 –

11

「外側」のカッコは、匿名サブクラスを作成していることを意味し、2番目のカッコはオブジェクトの初期化子です。初期化子はクラスのコンストラクタの前で実行されますが、superの呼び出しの後に(したがってスーパークラスの初期化子の後にも)呼び出されます。お互いを呼び出せないコンストラクタが複数ある場合や、通常のフィールドイニシャライザよりも複雑な初期化が必要なフィールドの場合は、finalのフィールドを開始する便利な方法である非匿名クラスでもイニシャライザを使用できます。初期化子がチェック例外を投げることができる場合はすべてのコンストラクタは、彼らはそれを投げることができる宣言する必要があり、

class X extends Y{ 
    private final int lulz; 

    private static boolean someCondition(){...} 
    private static boolean danger() throws SomeException { ... } 
    { // initalizer -- might throw SomeException! 
     lulz = someCondition()? danger() : 0; 
    } 
    public X(A a) throws SomeException { super(a); } 
    public X(B b) throws SomeException { super(b); } 
} 

class X extends Y{ 
    private final int lulz; 

    private static boolean someCondition(){...} 
    private static boolean danger() throws SomeException { ... } 
    public X(A a) throws SomeException { 
     super(a); 
     lulz = someCondition()? danger() : 0; 
    } 
    public X(B b) throws SomeException { 
     super(b); 
     lulz = someCondition()? danger() : 0; 
    } 
} 

それは以下のように書き換えることができます

は、このクラスを考えてみましょう。

4

あなたはanonymous classを作成し、このように、class Instance initialize Rイディオムを使用している:前回の回答で述べたように

class X { 
    private Y var1; 

    private X() { 
     Z context = new Z(
       new SystemThreadPool()) { 
        {      // This is the initialize idiom 
         var1 = new Y();  // 
        }      // 
       } 
     ); // BTW you are missing ")" 
    } 
} 
1

重中括弧の初期化は正しいです。

Javaのインスタンスメンバーを初期化するために、特定の手法を使用します。これは、クラスコンストラクターのいずれかがアクティブになったときに実行される共有されたコードブロックをクラス定義で定義する簡略な方法です。

私は、件名の幅広い観点から、official Java documentationsへのリンクを追加しています。

documentationから:インスタンス変数のための

初期化子ブロックだけ静的 初期化子ブロックのように見えますが、静的なキーワードなし:

{

// whatever code is needed for initialization goes here 

}

Javaコンパイラは初期化ブロックintをコピーします。すべてのコンストラクタ。 したがって、このアプローチを使用して、複数のコンストラクタ の間にコードブロックを共有できます。

関連する問題