What is Double Brace initialization in Java?

Java中的双括号初始化语法( {{ ... }} )是什么?


Double brace initialisation creates an anonymous class derived from the specified class (the outer braces), and provides an initialiser block within that class (the inner braces). eg

new ArrayList<Integer>() {{
   add(1);
   add(2);
}};

Note that an effect of using this double brace initialisation is that you're creating anonymous inner classes. The created class has an implicit this pointer to the surrounding outer class. Whilst not normally a problem, it can cause grief in some circumstances eg when serialising or garbage collecting, and it's worth being aware of this.


Every time someone uses double brace initialisation, a kitten gets killed.

Apart from the syntax being rather unusual and not really idiomatic (taste is debatable, of course), you are unnecessarily creating two significant problems in your application, which I've just recently blogged about in more detail here.

1. You're creating way too many anonymous classes

Each time you use double brace initialisation a new class is made. Eg this example:

Map source = new HashMap(){{
    put("firstName", "John");
    put("lastName", "Smith");
    put("organizations", new HashMap(){{
        put("0", new HashMap(){{
            put("id", "1234");
        }});
        put("abc", new HashMap(){{
            put("id", "5678");
        }});
    }});
}};

... will produce these classes:

Test$1$1$1.class
Test$1$1$2.class
Test$1$1.class
Test$1.class
Test.class

That's quite a bit of overhead for your classloader - for nothing! Of course it won't take much initialisation time if you do it once. But if you do this 20'000 times throughout your enterprise application... all that heap memory just for a bit of "syntax sugar"?

2. You're potentially creating a memory leak!

If you take the above code and return that map from a method, callers of that method might be unsuspectingly holding on to very heavy resources that cannot be garbage collected. Consider the following example:

public class ReallyHeavyObject {

    // Just to illustrate...
    private int[] tonsOfValues;
    private Resource[] tonsOfResources;

    // This method almost does nothing
    public Map quickHarmlessMethod() {
        Map source = new HashMap(){{
            put("firstName", "John");
            put("lastName", "Smith");
            put("organizations", new HashMap(){{
                put("0", new HashMap(){{
                    put("id", "1234");
                }});
                put("abc", new HashMap(){{
                    put("id", "5678");
                }});
            }});
        }};

        return source;
    }
}

The returned Map will now contain a reference to the enclosing instance of ReallyHeavyObject . You probably don't want to risk that:

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

3. You can pretend that Java has map literals

To answer your actual question, people have been using this syntax to pretend that Java has something like map literals, similar to the existing array literals:

String[] array = { "John", "Doe" };
Map map = new HashMap() {{ put("John", "Doe"); }};

Some people may find this syntactically stimulating.


  • The first brace creates a new Anonymous Inner Class.
  • The second set of brace creates an instance initializers like static block in Class.
  • For example:

       public class TestHashMap {
        public static void main(String[] args) {
            HashMap<String,String> map = new HashMap<String,String>(){
            {
                put("1", "ONE");
            }{
                put("2", "TWO");
            }{
                put("3", "THREE");
            }
            };
            Set<String> keySet = map.keySet();
            for (String string : keySet) {
                System.out.println(string+" ->"+map.get(string));
            }
        }
    
    }
    

    How it works

    First brace creates a new Anonymous Inner Class. These inner classes are capable of accessing the behavior of their parent class. So, in our case, we are actually creating a subclass of HashSet class, so this inner class is capable of using add() method.

    And Second set of braces are nothing but instance initializers. If you remind core java concepts then you can easily associate instance initializer blocks with static initializers due to similar brace like struct. Only difference is that static initializer is added with static keyword, and is run only once; no matter how many objects you create.

    more

    链接地址: http://www.djcxy.com/p/82398.html

    上一篇: 在一个语句中一次向HashMap添加多个条目

    下一篇: 什么是Java中的Double Brace初始化?