2009-09-03 3 views
41

Что делает {{ ... }} блок в следующем коде?Значение нового класса (...) {{...}} Инициализация idiom

class X { 

    private Y var1; 

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

} 
+5

Я думаю, что это непросто для Google для двойных фигурных скобок. –

+3

@Tom Hawtin: вы можете использовать Google для «двойной скобки» ... –

ответ

62

Это называется double curly brace initialization. (EDIT: ссылка удалена, 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"); 

Так что Безразлично» В этом случае имеет смысл, тогда как, например, Карты, у которых нет удобного помощника.

+0

@skaffman Это очень полезно в «жидкой java», такой как [JATL] (http://code.google.com/p/jatl) попытки. –

+6

Обратите внимание, что Arrays.asList() возвращает java.util.Arrays.ArrayList.ArrayList, а не java.util.ArrayList, который имеет ограниченную функциональность. – Asaf

+3

Эта техника сложна и имеет некоторые оговорки. В конечном итоге можно сломать контракт equals() или увеличить использование памяти без уважительной причины. Лучше избегать инициализации двойной привязки, если вы точно не знаете, что делаете. Посмотрите на [this] (http://www.ayp-sd.blogspot.com/2012/12/double-brace-initialization-in-java.html) сообщение для более подробной информации. –

11

«Внешние» фигурные скобки означают, что вы создаете анонимный подкласс, а вторая фигурная скобка - инициализатор объекта. Инициализатор запускается перед конструктором класса, но после любых вызовов super (и, следовательно, также после любых инициализаторов суперкласса). Вы также можете использовать инициализаторы в неанонимных классах, что является удобным способом для запуска полей final, если у вас есть несколько конструкторов, которые не могут называть друг друга, или поля, которые требуют более сложной инициализации, чем позволяют обычные инициализаторы полей.

Рассмотрим этот класс:

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

Это может быть переписано как:

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

Если инициализатор может бросить проверяемое исключение, все конструкторы должны объявить они могут бросить его.

4

Вы создаете anonymous class и используя class Instance initialize г идиомы, например:

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:

Initializer блоки для переменных экземпляра выглядят так же, как статические инициализатора блоков, но без статического ключевого слова:

{

// whatever code is needed for initialization goes here 

}

Компилятор Java копирует блоки инициализации int o каждый конструктор. Следовательно, этот подход может использоваться для совместного использования блока кода между несколькими конструкторами.