Значение нового класса (...) {{...}} Инициализация

Что означает {{ ... }} значение блока в следующем коде?

class X {

    private Y var1;

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

}

Ответ 1

Он назвал двойную фигурную скобку инициализации. (EDIT: ссылка удалена, архивировано здесь)

Это означает, что вы создаете анонимный подкласс, а код в двойных скобках - это в основном конструктор. Он часто используется для добавления содержимого в коллекции, потому что синтаксис 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");

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

Ответ 2

"Внешние" фигурные скобки означают, что вы создаете анонимный подкласс, а вторая фигурная скобка - инициализатор объекта. Инициализатор запускается перед конструктором класса, но после любых вызовов 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); }
}

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

Ответ 3

Вы создаете анонимный класс и используете класс Instance initialize r idiom, например:

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

Ответ 4

Как упоминалось в предыдущих ответах, правильная инициализация двойной фигурной скобки.

Он использует определенный метод для Инициализации экземпляров в Java. Это сокращенный способ определения в определении класса, общего блока кода, который будет запускаться при активации любого из конструкторов классов.

Я добавляю ссылку на официальную документацию Java описывая ее для более широкого обзора темы.

Из документации:

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

{

// whatever code is needed for initialization goes here 

}

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