Значение нового класса (...){{...}} идиома инициализации
Что значит {{ ... }}
блок означает в следующем коде?
class X {
private Y var1;
private X() {
Z context = new Z(new SystemThreadPool()) {{
var1 = new Y();
}};
}
}
4 ответа
Это называется инициализация двойной фигурной скобки. (РЕДАКТИРОВАТЬ: ссылка удалена, заархивированы здесь)
Это означает, что вы создаете анонимный подкласс, а код в двойных скобках по сути является конструктором. Он часто используется для добавления содержимого в коллекции, потому что синтаксис 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");
Так что в этом случае это не имеет особого смысла, в отличие, например, от Карт, у которых нет удобного помощника.
"Внешние" скобки означают, что вы создаете анонимный подкласс, вторые скобки являются инициализатором объекта. Инициализатор запускается до конструктора класса, но после любого 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); }
}
Если инициализатор может генерировать проверенное исключение, все конструкторы должны объявить, что могут его выбросить.
Вы создаете анонимный класс и используете класс инициализации Instance, например:
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 ")"
}
}
Как упоминалось в предыдущих ответах, инициализация двойной фигурной скобки является правильной.
Он использует особую технику для инициализации элементов экземпляра в Java. Это сокращенный способ определения в определении класса общего блока кода, который будет запускаться при активации любого из конструкторов классов.
Я добавляю ссылку на официальную документацию Java, описывающую ее для более широкого взгляда на предмет.
Из документации:
Блоки инициализатора для переменных экземпляра выглядят так же, как статические блоки инициализатора, но без ключевого слова static:
{
// whatever code is needed for initialization goes here
}
Компилятор Java копирует блоки инициализатора в каждый конструктор. Следовательно, этот подход можно использовать для совместного использования блока кода между несколькими конструкторами.