Что такое double brace инициализация?

142
28 сентября 2019, 12:50

Что означает синтаксис {{ }}(две двойных фигурных скобки) в Java?

Answer 1

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

Пример:

new ArrayList<Integer>() {{
   add(1);
   add(2);
}};

ArrayList - "главный", внешний класс, первая скобка - скобка внешнего класса, вторая скобка - скобка блока инициализации. Пространство внутри скобок - блок инициализации.

Созданный класс имеет неявный указатель this на внешний класс. Хотя обычно это не проблема, в некоторых случаях это может быть плохо(из-за создания классов), например, при сериализации или сборке мусора, и об этом стоит знать.

Java 9 ввел удобные методы List.of, Set.of и Map.of, которые следует использовать. Они быстрее и эффективнее, чем инициализатор с двойными скобками.

Проблемы при использовании такой конструкции:

1. Вы создаете слишком много анонимных классов

Каждый раз, когда вы используете двойную инициализацию, создается новый класс.

Пример

Map source = new HashMap(){{
    put("firstName", "John");
    put("lastName", "Smith");
    put("organizations", new HashMap(){{
        put("0", new HashMap(){{
            put("id", "1234");
        }});
        put("abc", new HashMap(){{
            put("id", "5678");
        }});
    }});
}};

будет создавать эти классы:

Test$1$1$1.class
Test$1$1$2.class
Test$1$1.class
Test$1.class
Test.class

Конечно, это не так много, но если вы используете эту конструкцию 10-100-1000 раз, то вы используете кучу памяти всего лишь ради синтаксического сахара.

2. Вы потенциально создаете утечку памяти! Если вы примените следующий код, например в методе, то вызывающие метод могут не подозревать о слишком больших ресурсах, которые невозможно собрать GC.

Больше о производительности при использовании двойных скобок(enSO).

Еще 1 пример инициализации с помощью двойных скобок:

private static class IndustrialRaverMonkey
  extends Creature.Base {{
    life = 46;
    strength = 35;
    charisma = 91;
    weapon = 2;
  }}
private static class DwarvenAngel
  extends Creature.Base {{
    life = 540;
    strength = 6;
    charisma = 144;
    weapon = 50;
  }}
Answer 2

Внутренние фигурные скобки эквивалентны описанию конструктора без параметров:

class Clazz {{System.out.println("hello");}}

это то же самое что

class Clazz {
     Clazz(){
        System.out.println("hello");
     }
}
READ ALSO
Gradle sync failed, implementations

Gradle sync failed, implementations

Не понимаю в чём проблема"Gradle sync failed"

107
Аналог static class (C#) на Java

Аналог static class (C#) на Java

Нагуглил несколько статей: в одной говорится, что синглтон идеален для хранения глобальных переменныхВ другой - что он (синглтон) таки может...

125
Возникает ошибка при выборке из бд в resultSet.next()

Возникает ошибка при выборке из бд в resultSet.next()

E/AndroidRuntime: FATAL EXCEPTION: main Process: comexample

158
Как из String JSON получить String anotherJSON, который он содержит

Как из String JSON получить String anotherJSON, который он содержит

Я получаю String jsonObject в контроллереСтруктура файла следующая:

169