Что такое синтаксис инициализации Double Brace ( {{ ... }}
) в Java?
java
initialization
double-brace-initialize
sgokhales
источник
источник
Ответы:
Инициализация двойной скобкой создает анонимный класс, производный от указанного класса ( внешние скобки), и обеспечивает блок инициализатора внутри этого класса ( внутренние скобки). например
Обратите внимание, что эффект использования этой двойной скобки заключается в том, что вы создаете анонимные внутренние классы. Созданный класс имеет неявный
this
указатель на окружающий внешний класс. Хотя обычно это не проблема, в некоторых случаях это может вызвать горе, например, при сериализации или сборке мусора, и об этом стоит знать.источник
Каждый раз, когда кто-то использует двойную инициализацию, котенка убивают.
Помимо того, что синтаксис довольно необычен и не совсем идиоматичен (вкус спорен, конечно), вы без необходимости создаете две существенные проблемы в своем приложении, о которых я недавно недавно более подробно писал в блоге .
1. Вы создаете слишком много анонимных классов
Каждый раз, когда вы используете двойную инициализацию, создается новый класс. Например, этот пример:
... будет производить эти классы:
Это довольно много для вашего загрузчика классов - ни за что! Конечно, это не займет много времени инициализации, если вы сделаете это один раз. Но если вы сделаете это 20 000 раз по всему корпоративному приложению ... всю эту кучу памяти только для небольшого количества "синтаксического сахара"?
2. Вы потенциально создаете утечку памяти!
Если вы возьмете приведенный выше код и вернете эту карту из метода, вызывающие этого метода могут ничего не подозревать о слишком больших ресурсах, которые невозможно собрать мусором. Рассмотрим следующий пример:
Возвращенный
Map
теперь будет содержать ссылку на включающий экземплярReallyHeavyObject
. Вы, вероятно, не хотите рисковать этим:Изображение с http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/
3. Вы можете делать вид, что у Java есть литералы карты
Чтобы ответить на ваш реальный вопрос, люди использовали этот синтаксис, притворяясь, что в Java есть что-то вроде литералов карты, аналогично существующим литералам массива:
Некоторые люди могут найти это синтаксически стимулирующим.
источник
{{...}}
и объявляется какstatic
поле, не должно быть никакой возможной утечки памяти, только один анонимный класс и никаких вложенных ссылок на экземпляры, верно?Map.of()
для этой цели, так что это будет лучшее решениеReallyHeavyObject
. Кроме того, анонимные внутренние классы захватывают все локальные переменные, используемые в теле класса, поэтому, если вы используете не только константы для инициализации коллекций или карт с этим шаблоном, экземпляры внутреннего класса будут захватывать все из них и продолжать ссылаться на них, даже если они фактически удалены из коллекция или карта. Поэтому в этом случае этим экземплярам не только требуется вдвое больше необходимой памяти для ссылок, но и возникает другая утечка памяти в этом отношении.Например:
Как это устроено
Первая скобка создает новый анонимный внутренний класс. Эти внутренние классы могут получить доступ к поведению своего родительского класса. Итак, в нашем случае мы фактически создаем подкласс класса HashSet, поэтому этот внутренний класс может использовать метод put ().
И второй набор скобок - не что иное, как инициализаторы экземпляра. Если вы напоминаете основные концепции Java, то вы можете легко связать блоки инициализатора экземпляра со статическими инициализаторами из-за сходной фигурной скобки, например struct Разница лишь в том, что статический инициализатор добавляется с ключевым словом static и запускается только один раз; независимо от того, сколько объектов вы создаете.
Больше
источник
Для забавного применения двойной инициализации см. Здесь Массив Двемти в Java .
Выдержка
А теперь, будьте готовы к
BattleOfGrottoOfSausageSmells
... и бекону!источник
Я думаю, что важно подчеркнуть, что в Java не существует такой вещи, как «инициализация двойной скобки» . На сайте Oracle нет этого термина. В этом примере используются две функции: анонимный класс и блок инициализатора. Похоже, что старый блок инициализатора был забыт разработчиками и вызывает некоторую путаницу в этой теме. Цитирование из документов Oracle :
Блоки инициализатора для переменных экземпляра выглядят так же, как статические блоки инициализатора, но без ключевого слова static:
источник
1. Не существует такой вещи, как двойные скобки:
я хотел бы отметить, что не существует такой вещи, как инициализация двойных скобок. Существует только обычный традиционный один блок инициализации скобки. Второй блок скобок не имеет ничего общего с инициализацией. Ответы говорят, что эти две скобки что-то инициализируют, но это не так.
2- Это не только анонимные классы, но и все классы:
почти все ответы говорят о том, что они используются при создании анонимных внутренних классов. Я думаю, что у людей, читающих эти ответы, будет впечатление, что это используется только при создании анонимных внутренних классов. Но это используется во всех классах. Чтение этих ответов выглядит как новая специальная функция, предназначенная для анонимных классов, и я думаю, что это вводит в заблуждение.
3- Цель состоит только в том, чтобы поместить скобки друг за другом, а не в новую концепцию.
Далее этот вопрос говорит о ситуации, когда вторая открывающая скобка находится сразу после первой открывающей скобки. При использовании в обычном классе обычно есть некоторый код между двумя скобками, но это совершенно одно и то же. Так что это вопрос размещения скобок. Так что я думаю, что мы не должны говорить, что это что-то новое, захватывающее, потому что это то, что мы все знаем, но просто написано с кодом в скобках. Мы не должны создавать новую концепцию под названием «инициализация двойной скобки».
4. Создание вложенных анонимных классов не имеет ничего общего с двумя фигурными скобками:
я не согласен с аргументом, что вы создаете слишком много анонимных классов. Вы создаете их не из-за блока инициализации, а только потому, что создаете их. Они будут созданы, даже если вы не использовали две скобки для инициализации, поэтому эти проблемы могут возникнуть даже без инициализации ... Инициализация не является фактором, который создает инициализированные объекты.
источник
Чтобы избежать всех негативных последствий инициализации двойной скобки, таких как:
делать следующие вещи:
Пример:
Использование:
Преимущества:
Недостатки:
И, как результат, у нас самый простой шаблон для Java-строителя.
Посмотреть все примеры на github: java-sf-builder-simple-example
источник
Это - среди прочего - ярлык для инициализации коллекций. Выучить больше ...
источник
Вы имеете в виду что-то вроде этого?
это инициализация списка массивов во время создания (хак)
источник
Вы можете поместить некоторые операторы Java как цикл для инициализации коллекции:
Но этот случай влияет на производительность, проверьте это обсуждение
источник
Как указывает @Lukas Eder, двойных скобок следует избегать инициализации коллекций.
Он создает анонимный внутренний класс, и, поскольку все внутренние классы сохраняют ссылку на родительский экземпляр, он может - и, скорее всего, на 99% - предотвратить сборку мусора, если на эти объекты коллекции ссылается больше объектов, чем просто объявляющего.
Java 9 ввел удобные методы
List.of
,Set.of
иMap.of
, которые следует использовать вместо. Они быстрее и эффективнее, чем инициализатор с двойными скобками.источник
Первая фигурная скобка создает новый анонимный класс, а вторая наборная фигурная скобка создает инициализаторы экземпляра, такие как статический блок.
Как и другие указали, это не безопасно использовать.
Однако вы всегда можете использовать эту альтернативу для инициализации коллекций.
источник
Похоже, это то же самое, что ключевое слово with, столь популярное во flash и vbscript. Это метод изменения того, что
this
есть, и ничего более.источник
this
есть. Синтаксис просто создает анонимный класс (поэтому любая ссылка на негоthis
будет ссылаться на объект этого нового анонимного класса), а затем использует блок{...}
инициализатора для инициализации вновь созданного экземпляра.