Unfortunately, some features of well known programming languages are much less known than others. Eventually, those unknown features are quite powerful and useful. Today I’m going to describe so called “double brace initialization” in Java, which is quite similar (and more powerful) than object initializers of C#.
I saw piece of code containing the following line:
static { v = new Vector() { { add(8); addAll(v); addAll(this); } }; }
My initial guess was that author made a mistake and such code won’t compile. But I was wrong since this code is completely valid Java code since about 2007. To clear things a bit more I wrote this simple Java class:
public class ComplexInitializers { ComplexInitializers() { System.out.println("Constructor"); } void a() { System.out.println("a"); } void b() { System.out.println("b"); } String c; void c() { System.out.println(c); } public static void main(String[] args) { ComplexInitializers ci = new ComplexInitializers() {{ System.out.println("Initialization list"); a(); b(); c = "c"; c(); }}; System.out.println(ComplexInitializers.class); System.out.println(ci.getClass()); } }
Which outputs:
Constructor Initialization list a b c class ComplexInitializers class ComplexInitializers$1
Lets list several observations about the output:
- Double brace initialization list is executed after constructor.
- We can also set variables and do what ever we want in context of the newly created class instance.
- Java compiler creates an anonymous class, which contains code specified inside double braces.
- Class of object created using double brace initialization differers of class we are specifying in the source code.
Basing on the observations one can understand what Java compiler does:
- Creates an anonymous subclass (outer curly brackets).
- Create an instance initialization block for the anonymous subclass (inner curly brackets).
So in fact there is nothing new (or magic) about this feature, it’s just a joint usage of two other features of Java language:
- anonymous subclasses
- instance initialization blocks
But when these features are used together, it gives us a qualitative change, which can make code prettier in some use cases.
Be aware about creating additional class for each double initialization block as well as of some runtime overhead because of additional derived class in class hierarchy.
Also since we use subclassing, this won’t work with final classes.