Double Brace Initialization


Java doesn't have a convenient literal syntax for collections (lists, maps, sets, etc.). This makes creating constant collections or passing collections to functions quite laborious. Every time you have to

1.     Declare a variable for a temporary collection
2.     Create a new empty collection and store a reference to it in the variable
3.     Put things into the collection
4.     Pass the collection to the method
E.g. To pass a set to a method:

 
 Set<String> validCodes = new HashSet<String>();
 validCodes.add("XZ13s");
 validCodes.add("AB21/X");
 validCodes.add("YYLEX");
 validCodes.add("AR2D");
 removeProductsWithCodeIn(validCodes);
 
Or to initialize a set of constants:

 
private static final Set<String> VALID_CODES = new HashSet<String>();
 static {
                    validCodes.add("XZ13s");
                    validCodes.add("AB21/X");
                    validCodes.add("YYLEX");
                    validCodes.add("AR2D");
 }
 

But... you can create and initialize a new collection as an expression by using the "double-brace" syntax:
E.g.

 private static final Set<String> VALID_CODES = new HashSet<String>() {{
                    add("XZ13s");
                    add("AB21/X");
                    add("YYLEX");
                    add("AR2D");
 }};

Or:
 
removeProductsWithCodeIn(new HashSet<String>() {{
                    add("XZ13s");
                    add("AB21/X");
                    add("YYLEX");
                    add("AR5E");
 }});
 

The first brace creates a new AnonymousInnerClass, the second declares an instance initializer block that is run when the anonymous inner class is instantiated. This type of initializer block is formally called an "instance initializer", because it is declared within the instance scope of the class -- "static initializers" are a related concept where the keyword static is placed before the brace that starts the block, and which is executed at the class level as soon as the classloader completes loading the class (specified at http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.6) The initializer block can use any methods, fields and final variables available in the containing scope, but one has to be wary of the fact that initializers are run before constructors (but not before superclass constructors).
This only works for non-final classes because it creates an anonymous subclass. Obviously, this is not limited to collections; it can be used to initialize any kind of object -- for example Gui objects:
 
add(new JPanel() {{
                    setLayout(...);
                    setBorder(...);
                    add(new JLabel(...));
                    add(new JSpinner(...));
 }});
 


Comments

Popular posts from this blog

SinglePass Terms of Service

Jasper Report Viruatization

JasperReports Tutorial