Java instance initializers

I have been playing around with some UI mock ups lately and it is often that I have code that looks like the following:

...
add(new Label("Some text"));
...

If I want to see what Some text looks like in a different color or font then I need to extract the label creation to a local variable and then set the appropriate members. Since I’m a lazy lazy man I was getting tired of this. Luckily I remembered about instance initializers. Because of instance initializers you can do the following:

...
add(new Label("Some text") {{ setFont(someFont); }});
...

{{ and }} are not new tokens. Writing it another way makes it more clear:

...
add(new Label("Some text")
{
{
setFont(someFont);
}
});
...

The only question that remains is: when is the instance initializer executed? You can read section 8.8.5.1 of the JLS if you want. (The problem that I have with section 8.8.5.1 is that it is for explicit constructor invocations which doesn’t seem to be the case for this example but I cannot find another reference to instance initializers in the JLS.) The code below provides a clearer answer to the question.

class PreTest {
{System.err.println("PreTest First");}
public PreTest() {
System.err.println("PreTest constructor");
}
{System.err.println("PreTest Second");}
}
class Test extends PreTest {
{System.err.println("Test First");}
public Test() {
System.err.println("Test constructor");
}
{System.err.println("Test Second");}
public Test(final int number) {
this();
System.err.println("Test constructor(" + number + ")");
}
{System.err.println("Test Third");}
public void method() {
System.err.println("Test method");
}
{System.err.println("Test Fourth");}
}
class Dummy {
public Dummy() {}
public void go(Test test) {}
}
final Dummy dummy = new Dummy();
dummy.go(new Test(10) {{ method(); }});

When executed, the following is output:

PreTest First
PreTest Second
PreTest constructor
Test First
Test Second
Test Third
Test Fourth
Test constructor
Test constructor(10)
Test method

An instance initializer is executed during construction but after all other instance initializers and all (appropriate) constructors have finished.

I should point out that this “trick” is also great in unit tests for populating collections.

...
something.addList(new ArrayList() {{ add("1"); add("2"); add("3"); }});
...
foo.addMap(new HashMap() {{ put("1", "one"); put("2", "two"); }});
...
Advertisements

5 comments

  1. Excellent tip! I’m one of the few people who seems to even remember that instance initializers exist at all 🙂 and I’ve /certainly/ never seen them used in this novel fashion. Very clever.

  2. Good tip! I’ve always been a bit annoyed at the relative verbosity of initializing a HashMap compared to Ruby or Javascript. This syntax makes it a bit easier. Surprised I haven’t seen it used more.

  3. Good example! Your example is very readable and gives me a very clear understanding of instance initializers and their utility.

  4. Your test actually shows that all instance initializers are executed BEFORE constructor.
    I just got the same puzzling answer myself, and found your notice to confirm.
    Strange thing is, that in my own tests I assigned some instance variables in initializers. So, initializer assigns those vars BEFORE constructor (and supposedly those vars should not even exist), and constructor overrides them.
    In fact, I expected the opposite to happen.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s