Showing posts with label Why to avoid double Brace Initialization?. Show all posts
Showing posts with label Why to avoid double Brace Initialization?. Show all posts

Sunday, September 18, 2016

Don’t use Double Brace Initialization – double curly braces Anti pattern


·      -   Double brace initializer is nothing but it is instance initializer inside a inner class.
·      =  Double Brace Initialization looks convenient for variable initialization for collections (map,List,set..). This feel good, because we can declare and initialize collections at the same time.
·        This means we can declare and initialize at the same time using instance initializer.
E.g we a list and we want to add some elements to this like "A","B","C". What we will do.
List<String> list = new ArrayList<String>(); 
list.add("A"); 
list.add("B"); 
list.add("C"); 
Also we can initialize as below. But this is a unmodifiable list, if we try to modify this list, it will give java.lang.UnsupportedOperationException

List<String> listOfLetters1 = Arrays.asList("A", "B", "C"); 
                         
Initialize using Double braces:
List<String> list = new ArrayList<String>()
{
{
add("A"); 
add("B"); 
add("C"); 
}
};
It’s look pretty and simple,  we can do initialization in one line.


What is Double Brace Initialization?
·        Double brace initializer is nothing but it is instance initializer inside a inner class.

instance initializers to instantiate collections
instantiating and initializing collections without having to manually populate the list.
Declaration and initialization in one line.
This is not a special {{ symbol but two { given different meanings. The first { shows this is an anonymous class, the second { means the start of an initializer block.
How the compiler will consider this? or why it is saying avoid this ? or why it is calling as anti pattern ?
·        Creating anonymous class while compilation – that decrease the performance.

Double brace initializer is just a initializer inside (inner braces) anonymous inner class(outer braces).
The outer ‘{ ‘ represent anonymous  inner class
So every time when we are creating a map or any collection using double brace initializer means your creating an anonymous inner class.

At run time compiler will generate *.class file for each anonymous inner class and that will loaded and invoked by class loader at runtime.
e.g>
public class test  {
public test {

List<String> list = new ArrayList<String>() {{
add("A"); 
add("B"); 
add("C"); 
}};
}
public static void main(String[] args) {
        new test();
    }
}

For the above example after compilation this will be having test.class, test$1.class
i.e for every anonymous inner class a ‘.class’ file will be gnereating.

So at the run time class loader will invoke this, this will reduce overall performance of your application.

·        Inner classes Keeping a ‘this’ reference to the outer classes- creating memory leak
For non-static anonymous inner classes that will always keep reference to their enclosing instance. .i.e the inner class always have ‘this’ reference (this$0) to the outer class. This will lead to memory leak- since this is preventing GC from freeing up the occupied memory.
That is to, serialize the collection you have to serialize the entire enclosing class.
·        Doesn’t support empty  diamond operator (<>)
From Java 7 onwards, we will be to declare variables using <>,
List<String> list = new ArrayList< >(); 
But double brace intializrer is not supporting this.
List<String> list = new ArrayList< >()
{
{
add("A"); 
add("B"); 
add("C"); 
}
};
The above code will throw compilation error.
Because of the above all disadvantages, we are not using double brace initializer nowadays, so this become an antipattern.
Where to use:  Used only for testing, demos and debugging.
In Java 8 we have  Stream API and Collectors available for initialization of collections.
List<String> list = Collections.unmodifiableList(Stream.of(("A", "B", "C").collect(toList()));
But the streams collectors make no guarantees about the mutability of collections they return