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.