1.Overview
In this quick tutorial, we’ll show how double braces can be used for creating and initializing objects in a single Java expression.
We’ll also look at why this technique can be considered an anti-pattern.
2.Standard Approach
Normally we initialize and populate a set of countries as follows:
@Test
public void whenInitializeSetWithoutDoubleBraces_containsElements() {
Set<String> countries = new HashSet<String>();
countries.add("India");
countries.add("USSR");
countries.add("USA");
assertTrue(countries.contains("India"));
}
As can be seen from above example, we are doing the following:
- Create an instance of HashSet
- Add countries to the HashSet
- Finally, we assert whether the country is present in the HashSet
3.Using Double Brace
However, we can actually combine the creation and initialization in a single statement; this is where we make use of double braces:
@Test
public void whenInitializeSetWithDoubleBraces_containsElements() {
Set<String> countries = new HashSet<String>() {
{
add("India");
add("USSR");
add("USA");
}
};
assertTrue(countries.contains("India"));
}
As can be seen from above example, we are:
- Creating an anonymous inner class which extends HashSet
- Providing an instance initialization block which invokes the add
method and adds the country name to the HashSet - Finally, we can assert whether the country is present in the HashSet
4.Advantages of Using Double Braces
There are some simple advantages of using double braces:
- Fewer lines of code compared to the native way of creation and
initialisation - The code is more readable
- Creation initialization is done in the same expression
5.Disadvantages of Using Double Braces
Disadvantages of using double braces are:
- Obscure, not widely known way to do the initialization
- It creates an extra class every time we use it
- Doesn’t support the use of the “diamond operator” – a feature
introduced in Java 7 - Doesn’t work if the class we are trying to extend is marked final
- Holds a hidden reference to the enclosing instance, which may cause
memory leaks
It’s due to these disadvantages that double brace initialization is considered as an anti-pattern.
6. Alternatives
6.1. Stream Factory Methods
Instead, we can make good use of the new Java 8 Stream API to initialize our Set:
2
3
4
5
6
7
@Test
public void whenInitializeUnmodifiableSetWithDoubleBrace_containsElements() {
Set<String> countries = Stream.of("India", "USSR", "USA")
.collect(collectingAndThen(toSet(), Collections::unmodifiableSet));
assertTrue(countries.contains("India"));
}
6.2. Java 9 Collections Factory Methods
Also, Java 9 will bring a set of useful factory methods that will make the following possible:
List<String> list = List.of("India", "USSR", "USA");
Set<String> set = Set.of("India", "USSR", "USA");
You can read more about this in this article.