Java Dregs: Double Brace Initialization

Hi there! This is Java Dregs for April 1st, 2013!

If you’ve ever tried one of those dynamic languages, like Python or Ruby, that are so popular with the kids these days, you might have noticed that those languages have special literal syntaxes for declaring common data structures like maps and lists. While Java obviously has the advantage when it comes to the number of unique data structures supported out of the box, it’s true that initializing these structures with values can be a little verbose.

For instance, let’s say we’re writing a class that represents a cafe. The cafe has a list of available coffee bean varieties, implemented as a Set of strings.

This list of varieties is static. In order to initialize it at program startup, we open a separate static initializer block and add each variety to the list individually.

Just to verify that this works, we add a simple main function and run the code.

import java.util.*;

public class Cafe {
    public static Set<String> varieties = new HashSet<String>();

    static {
        varieties.add("Guatemala");
        varieties.add("Tanzanian Peaberry");
        varieties.add("Monsooned Malabar");
    }

    public static void main(String[] args) {
        System.out.println("Bean varieties: " + varieties);
    }
}

Now, unlike Ruby’s “Hashes” or Python’s “dictionaries”, Java doesn’t have a literal syntax for sets. But there is a way to declare this list of varieties a little more concisely. It uses a technique known as “double brace initialization”.

To use this technique, we’ll modify the declaration of the varieties set. After the call to the constructor, we’ll put double open braces. We’ll move the addition of bean varieties into this new block, and then close the block with a set of double closing braces. Finally, we’ll remove the explicit reference to the varieties variable within this block.

import java.util.*;

public class Cafe {
    public static Set<String> varieties = new HashSet<String>() {{
            add("Guatemala");
            add("Tanzanian Peaberry");
            add("Monsooned Malabar");
        }};

    public static void main(String[] args) {
        System.out.println("Bean varieties: " + varieties);
    }
}

When we compile and run this code, we get the same output as before.

So what’s going on here? The explanation is a little bit tricky. The outer set of braces declares an anonymous class inheriting from HashSet. Within the outer braces we are defining this new, anonymous class.

The inner braces begin an initializer block for the anonymous class. Since initializer blocks are called in the context of a new instance of the class, we can invoke instance methods like add() directly.

The upshot is that the varieties variable is initialized with a reference to the sole instance of an anonymous subclass of HashSet, and that sole instance is loaded with coffee varieties as part of its construction. While this isn’t quite a literal Set syntax, it enables us to declare and define the list of bean varieties at once in a single expression, instead of spread across two separate expressions.

That’s all for today. Happy hacking!