Double Brace Initialization Idiom and its drawbacks

This post is inspired by the Double Brace Initialization concept explained here. This technique can be used for creating and initializing objects and represent these operations in a single expression. And the efficiency of this technique has been heavily discussed on stackoverflow.

Conventional way to create and populate an object

We all are familiar with creating and populating data in an ArrayList, we generally do something like:

List<String> names2 = new ArrayList<>();
names2.add("Name1");
names2.add("Name2");
names2.add("Name3");
names2.add("Name4");

there’s yet another approach by using Arrays.asList, but this creates an immutable list, so any further add operations results in UnsupportedOperationException. Lets look at that example as well:

List<String> names3 = Arrays.asList("name1","name2", "name3");

//This throws java.lang.UnsupportedOperationException
names3.add("names4");

Using Double brace initialization idiom

So how does Double Brace Initialization help us here? Lets look at an example for that as well:

List<String> names = new ArrayList<String>(){{
  add("Mr. ABC");
  add("Mr. XYZ");
  add("Mrs. PQR");
  add("MNOP");
}};

It gets the name for the double {{ }} present in the expression. In the above example we are doing 2 things:
1. Create an anonymous inner class which extends ArrayList.
2. Provide an instance initialization block which invokes the add method and adds the required elements. Please read this to know more about initialization blocks.

The advantage we have with this approach is that we can combine creation and initialization into an expression and pass around into different methods. Lets look at an example for this:

class MySomeClass {
  protected String someStrProp;
  protected int someIntProp;
  protected boolean someBoolProp;
}

public class DoubleBraceInitialisationDemo {
  public static void main(String[] args) {
    //There are 3 things happening in the code below:
    //1. Extend the class MySomeClass
    //2. Create an instance of the extension
    //1 and 2 correspond to creating Anonymous inner class
    //3. Create a instance initializer to set values for properties.
    someMethod(new MySomeClass() {{
      someBoolProp = true;
      someIntProp = 12;
      someStrProp = "Some String";
    }});
  }
  
  static void someMethod(MySomeClass someObj) {
    System.out.println(someObj.getSomeIntProp());
    System.out.println(someObj.getSomeStrProp());
    System.out.println(someObj.isSomeBoolProp());
  }
}

Though we say that this approach can be used in creating an object and initializing it in a single expression, we have to be aware that we are not creating the object of that class instead we are creating an object of the extension of that class under consideration.

Drawbacks of using Double Brace Initialization approach

Overusing or abusing this idiom can often lead to bloated number of class files generated and this can cause performance issues as noted in the discussion here. This is because this idiom makes use of anonymous inner classes to achieve the required result.

And the other drawback is that this doesn’t support use of “Diamond operator”, a feature introduced in Java 7, while creating instances of generic types. Let me explain this with an example:

//This is using Double brace initialization.
Map<Integer, String> numbers = 
          new HashMap<Integer, String>() {{
  put(1, "One");
  put(2, "Two");
  put(4, "Four");
  put(7, "Seven");
}};
//Diamond operator in Java 7 allows us to:
Map<Integer, String> myMap = new HashMap<>();

//But one cannot use this feature while using Double brace initialization
Map<Integer, String> numbers2 = 
          new HashMap<>() {{
  put(1, "One");
  put(2, "Two");
  put(4, "Four");
  put(7, "Seven");
}};
//The above code gives an error stating: 
//"Cannot use <> with anonymous inner classes"

This Double brace initialization is an idiom that is good to be aware of as it involves use of anonymous inner class and instance initialization blocks. I think this will be a good Java trivia during the interviews.

6 thoughts on “Double Brace Initialization Idiom and its drawbacks”

  1. This idiom is used so rarely that I didn’t recognize the disadvantages yet, but of course you’re right. Sure the double brace idiom doesn’t create an instance of the desired class, but a subclass of it – thus causing all kinds of unexpected problems. Nice article, thanks!

    Reply
  2. As cool as this idiom is, I would refrain from using it simply because it would confuse a hell of lot of people in my company. It’s almost like adding a new construct into Java

    Reply
  3. Most of the criticism in the linked Stack Overflow question evolves around class loading and possibly serialisation. In my opinion, the most severe drawback of “accidentally” shipping enclosing instances with trivial maps is the potential of creating severe memory leaks. I’ve blogged about that here:

    http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/

    Nice catch with the diamond operator, too! I wasn’t aware of that limitation. Do you know why that is not allowed? I.e. what EG decision prevented this?

    Reply

Leave a Reply

Discover more from Experiences Unlimited

Subscribe now to keep reading and get access to the full archive.

Continue reading