2009-09-03 3 views
41

Was bedeutet {{ ... }} Block im folgenden Code bedeuten?Bedeutung der neuen Klasse (...) {{...}} Initialisierung idiom

class X { 

    private Y var1; 

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

} 
+5

Ich denke, es ist nicht einfach, nach Doppelstreben zu googeln. –

+3

@Tom Hawtin: Sie können Google stattdessen für "double brace" verwenden ... –

Antwort

62

Es heißt double curly brace initialization. (BEARBEITEN: Link entfernt, archived here)

Es bedeutet, dass Sie eine anonyme Unterklasse erstellen und der Code innerhalb der doppelten Klammern im Grunde ein Konstruktor ist. Es wird oft zum Hinzufügen von Inhalten zu Sammlungen verwendet, da die Syntax von Java zum Erstellen von Daten, die im Wesentlichen Sammlungskonstanten sind, etwas peinlich ist.

So könnten Sie tun:

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

statt:

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

ich so eigentlich nicht, und es vorziehen, dies zu tun:

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

So es doesn‘ Das macht in diesem Fall viel Sinn, während es z. B. für Maps, die keinen praktischen Helfer haben, sinnvoll ist.

+0

@skaffman Es ist sehr nützlich in "fluid java" wie dem [JATL] (http://code.google.com/p/jatl) Versuche. –

+6

Beachten Sie, dass Arrays.asList() java.util.Arrays.ArrayList.ArrayList und nicht java.util.ArrayList zurückgibt, da diese Funktionalität eingeschränkt ist. – Asaf

+3

Diese Technik ist schwierig und hat einige Vorbehalte. Es ist möglich, mit gebrochenem equals() - Vertrag oder erhöhter Speicherauslastung ohne triftigen Grund zu enden. Es ist besser, die doppelte Klammerinitialisierung zu vermeiden, wenn Sie nicht genau wissen, was Sie tun. Sehen Sie sich [diese] (http://www.ayp-sd.blogspot.com/2012/12/double-brace-initialization-in-java.html) Post für weitere Details an. –

11

Die "äußeren" geschweiften Klammern bedeuten, dass Sie eine anonyme Unterklasse erstellen, die zweite geschweifte Klammern sind die Objektinitialisierer. Der Initialisierer wird vor dem Konstruktor der Klasse ausgeführt, aber nach irgendwelchen super Aufrufen (und daher auch nach irgendwelchen Superklassen-Initialisierern). Sie können Initialisierer auch in nicht anonymen Klassen verwenden, was eine bequeme Möglichkeit ist, Felder final zu initiieren, wenn Sie mehrere Konstruktoren haben, die sich nicht gegenseitig aufrufen können, oder Felder, die eine komplexere Initialisierung als übliche Feldinitialisierungen erfordern.

Betrachten Sie diese Klasse:

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; 
    } 
} 

Es umgeschrieben werden:

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); } 
} 

Wenn die Initialisierung eine geprüfte Ausnahme auslösen können, sind alle Konstrukteure erklären müssen sie es werfen kann.

4

Sie schaffen eine anonymous class und mit Hilfe der class Instance initialize r Idiom, wie folgt aus:

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

Wie bereits in früheren Antworten erwähnt, doppelt geschweiften Klammer Initialisierung korrekt ist.

Es verwendet eine spezielle Technik zu Initialisieren Instanz Mitglieder in Java. Es ist eine Abkürzung, um in einer Klassendefinition einen gemeinsamen Codeblock zu definieren, der ausgeführt wird, wenn einer der Klassenkonstruktoren aktiviert wird.

Ich füge den Link zu der official Java documentations Beschreibung für eine umfassendere Sicht auf das Thema.

Von der documentation:

Initializer Blöcke zum Beispiel Variablen aussehen wie statische initializer Blöcke, aber ohne das Schlüsselwort static:

{

// whatever code is needed for initialization goes here 

}

Der Java-Compiler kopiert Initialisierungsblöcke int o jeder Konstruktor. Daher kann dieser Ansatz verwendet werden, um einen Codeblock zwischen mehreren Konstruktoren zu teilen.