Why You Should Avoid Double‑Brace Initialization in Java (And Better Alternatives)
The article explains why the double‑brace initialization trick for Java collections is problematic—causing obscure code, extra classes, memory leaks, and serialization issues—and offers safer alternatives such as a custom MapBuilder and the upcoming Map.of factory methods.
Introduction
Java does not provide a literal collection‑initialization syntax, so some developers resort to the double‑brace initialization trick to simplify Map creation. This article details why that trick should be avoided and presents better alternatives.
The Technique and Its Drawbacks
Typical Map initialization requires multiple statements:
Map<Integer, String> names = new HashMap<>();
names.put(1, "one");
names.put(2, "two");
names.put(3, "three");If the Map is a static final field, developers often use a static block, making the code even more verbose:
private static final Map<Integer, String> NAMES;
static {
Map<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
NAMES = Collections.unmodifiableMap(map);
}With double‑brace initialization the code looks like this:
private static final Map<Integer, String> NAMES = new HashMap<Integer, String>() {{
put(1, "one");
put(2, "two");
put(3, "three");
}};The right‑hand side actually creates an anonymous subclass of HashMap that contains an instance‑initialization block. Although it works, it has several serious drawbacks:
Obscure syntax : The double braces are confusing to readers unfamiliar with the trick.
Extra class file : The compiler generates an additional .class file, increasing the JVM’s class‑loading overhead and memory usage.
Hidden memory leaks : The anonymous subclass holds an implicit reference to the enclosing instance. If a method returns such a map, the enclosing object cannot be garbage‑collected, leading to memory leaks.
Serialization problems : The anonymous subclass is not serializable, causing NotSerializableException. Making the outer class serializable merely propagates the issue.
Because of these reasons, the double‑brace initialization trick should be avoided.
Alternative Approaches
A common replacement is to create a MapBuilder utility:
import java.util.HashMap;
import java.util.Map;
public final class MapBuilder<K, V> {
private final Map<K, V> map = new HashMap<>();
public MapBuilder<K, V> put(K key, V value) {
map.put(key, value);
return this;
}
public Map<K, V> build() {
return map;
}
}Usage example:
public class Example {
private static final Map<Integer, String> NAMES = new MapBuilder<Integer, String>()
.put(1, "one")
.put(2, "two")
.put(3, "three")
.build();
}This approach adds only a few lines of code but eliminates all the drawbacks of double‑brace initialization.
Java 9 Improvements
Java 9 does not introduce collection literals, but JEP‑269 adds convenient factory methods such as Map.of:
private static final Map<Integer, String> NAMES = Map.of(
1, "one",
2, "two",
3, "three"
);For Java 8 or earlier, developers can either use a custom MapBuilder or implement similar helper methods themselves. In any case, avoid the double‑brace initialization trick.
Cognitive Technology Team
Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
