Java, a versatile and widely-used programming language, offers various idioms and patterns to make developers' lives easier. One such idiom that gained popularity but is now considered an anti-pattern is the Double Brace Initialization. In this article, we delve deep into this idiom, understanding its pros, cons, and better alternatives.
Understanding Double Brace Initialization
Double Brace Initialization is an idiom in Java that allows for the initialization of collections, such as lists, sets, and maps, at the time of their declaration. This idiom became popular due to the absence of a standard way to simultaneously create and initialize collections in Java.
For instance, initializing an unmodifiable list with a few elements traditionally requires multiple lines of code:
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(5);
list.add(7);
List<Integer> unmodifiableList = Collections.unmodifiableList(list);
However, with Double Brace Initialization, the same can be achieved in a single line:
List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>() {{
add(2);
add(3);
add(5);
}});
Similarly, HashMaps can be initialized with values using this idiom:
Map<Integer, String> intToString = new HashMap<Integer, String>() {{
put(1, "one");
put(2, "two");
put(3, "three");
}};
Advantages and Disadvantages
Pros:
- Conciseness: Reduces the number of lines of code.
- Simultaneous Creation and Initialization: Allows for both in a single expression.
Cons:
- Obscurity: Relies on the instance initializer construct of anonymous classes, making it less intuitive.
- Additional Overhead: Every usage results in the creation of an extra class.
- Potential Memory Leaks: Holds a hidden reference to the enclosing instance.
Given these drawbacks, Double Brace Initialization is now viewed as an anti-pattern in Java.
Superior Alternatives
Java offers better alternatives to achieve the same results without the pitfalls of Double Brace Initialization.
Using Copy Constructors:
One can create and initialize an ArrayList with values in a single line using the copy constructor:
List<Integer> list = Collections.unmodifiableList(
new ArrayList<>(Arrays.asList(2, 3, 5))
);
Leveraging Java 8’s Stream API:
For those using Java 8, the Stream API provides another alternative:
List<String> list = Collections.unmodifiableList(
Stream.of("abc", "bcd", "cde").collect(toList())
);
For sets:
Set<String> set = Collections.unmodifiableSet(
Stream.of("abc", "bcd", "cde").collect(toSet())
);
Conclusion
While Double Brace Initialization offers a concise way to initialize collections, its disadvantages make it less suitable for production code. Developers are advised to opt for alternatives like copy constructors or the Stream API, which are more efficient and intuitive.