Meaning of new Class(…){{…}} initialization idiom [duplicate]

一曲冷凌霜 提交于 2019-11-26 16:10:56
cletus

It's called double curly brace initialization. (EDIT: Link removed, archived here)

It means you're creating an anonymous subclass and the code within the double braces is basically a constructor. It's often used to add contents to collections because Java's syntax for creating what are essentially collection constants is somewhat awkward.

So you might do:

List<String> list = new ArrayList<String>() {{
  add("one");
  add("two");
  add("three");
}};

instead of:

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

I actually don't like that and prefer to do this:

List<String> list = Arrays.asList("one", "two", "three");

So it doesn't make much sense in that case whereas it does for, say, Maps, which don't have a convenient helper.

The "outer" braces mean that you're making an anonymous subclass, the second braces are the object initializer. The initializer is run before the class' constructor, but after any super calls (and therefore also after any superclass initializers). You can use initializers in non-anonymous classes, too, which is a convenient way to initiate final fields if you have several constructors which cannot call each other, or fields which need more complex initialization than usual field initializers allow.

Consider this class:

class X extends Y{
    private final int lulz;

    private static boolean someCondition(){...}
    private static boolean danger() throws SomeException { ... }
    public X(A a) throws SomeException {
        super(a); 
        lulz = someCondition()? danger() : 0;
    }
    public X(B b) throws SomeException {
        super(b); 
        lulz = someCondition()? danger() : 0;
    }
}

It could be rewritten as:

class X extends Y{
    private final int lulz;

    private static boolean someCondition(){...}
    private static boolean danger() throws SomeException { ... }
    { // initalizer -- might throw SomeException!
        lulz = someCondition()? danger() : 0;
    }
    public X(A a) throws SomeException { super(a); }
    public X(B b) throws SomeException { super(b); }
}

If the initializer can throw a checked exception, all constructors must declare they can throw it.

You are creating an anonymous class and using the class Instance initializer idiom, like this:

class X {
    private Y var1;

    private X() {
        Z context = new Z(
               new SystemThreadPool()) {
                   {                        // This is the initialize idiom
                       var1 = new Y();      //
                   }                        //
               }
          );  // BTW you are missing ")"
    }
}

As mentioned in previous answers, double curly brace initialization is correct.

It uses a specific technique to Initializing Instance Members in Java. It is a shorthand way for defining in a class definition, a shared block of code that will run when any of the class constructor is activated.

I am adding the link to the official Java documentations describing it for more broader view on the subject.

From the documentation:

Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:

{

// whatever code is needed for initialization goes here 

}

The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!