«1. Обзор

В этом кратком руководстве мы покажем, как можно использовать двойные фигурные скобки для создания и инициализации объектов в одном выражении Java.

Мы также рассмотрим, почему этот метод можно считать антишаблоном.

2. Стандартный подход

Обычно мы инициализируем и заполняем набор стран следующим образом:

@Test
public void whenInitializeSetWithoutDoubleBraces_containsElements() {
    Set<String> countries = new HashSet<String>();                
    countries.add("India");
    countries.add("USSR");
    countries.add("USA");
 
    assertTrue(countries.contains("India"));
}

Как видно из приведенного выше примера, мы делаем следующее:

  1. Create an instance of HashSet
  2. Add countries to the HashSet
  3. Finally, we assert whether the country is present in the HashSet

3. Использование двойной скобки

Однако на самом деле мы можем объединить создание и инициализацию в одном операторе; здесь мы используем двойные фигурные скобки:

@Test
public void whenInitializeSetWithDoubleBraces_containsElements() {
    Set<String> countries = new HashSet<String>() {
        {
           add("India");
           add("USSR");
           add("USA");
        }
    };
 
    assertTrue(countries.contains("India"));
}

Как видно из приведенного выше примера, мы:

  1. Creating an anonymous inner class which extends HashSet
  2. Providing an instance initialization block which invokes the add method and adds the country name to the HashSet
  3. Finally, we can assert whether the country is present in the HashSet

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

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

    Меньше строк кода по сравнению с собственным способом создания и инициализации. Код более читабелен. Инициализация создания выполняется в том же выражении.

5. Недостатки использования двойных фигурных скобок. ~~ Малопонятный, малоизвестный способ инициализации. Он создает дополнительный класс каждый раз, когда мы его используем. класс, который мы пытаемся расширить, помечен как final Содержит скрытую ссылку на объемлющий экземпляр, что может вызвать утечку памяти

Именно из-за этих недостатков инициализация двойными скобками считается антишаблоном.

    6. Альтернативы

6.1. Методы фабрики потоков

Вместо этого мы можем эффективно использовать новый Java 8 Stream API для инициализации нашего набора:

6.2. Фабричные методы коллекций Java 9

Кроме того, Java 9 принесет набор полезных фабричных методов, которые сделают возможным следующее:

@Test
public void whenInitializeUnmodifiableSetWithDoubleBrace_containsElements() {
    Set<String> countries = Stream.of("India", "USSR", "USA")
      .collect(collectingAndThen(toSet(), Collections::unmodifiableSet));
 
    assertTrue(countries.contains("India"));
}

Подробнее об этом можно прочитать в этой статье.

7. Заключение

List<String> list = List.of("India", "USSR", "USA");
Set<String> set = Set.of("India", "USSR", "USA");

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

Реализацию этих примеров можно найти в проекте GitHub — это проект на основе Maven, поэтому его легко импортировать и запускать как есть.

«

The implementation of these examples can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as-is.