Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I recently came across a Java construct I have never seen before and was wondering whether I should use it. It seems to be called initializer blocks.

public class Test {
  public Test() { /* first constructor */ }
  public Test(String s) { /* second constructor */ }

  // Non-static initializer block - copied into every constructor:
  {
    doStuff();
  }
}

The code block will be copied into each constructor, i.e. if you have multiple constructor you do not have to rewrite code.

However, I see three main drawbacks using this syntax:

  1. It is one of the very few cases in Java where the order of your code is important, as you can define multiple code blocks and they will be executed in the order they are written. This seems harmful to me as simply changing the order of code blocks will actually change the code.
  2. I do not really see any benefits by using it. In most cases, the constructors will call each other with some pre-defined values. Even if this is not the case, the code could simply be put into a private method and called from each constructor.
  3. It reduces readability, as you could put the block at the end of the class and the constructor is normally at the beginning of the class. It is quite counter-intuitive to look at a completely different part of a code file if you do not expect that to be necessary.

If my above statements are true, why (and when) was this language construct introduced? Are there any legitimate use cases?

share|improve this question
3  
The example you've posted doesn't include anything that looks like an initializer block. – Simon B May 12 '14 at 15:01
4  
@SimonBarker look again – the { doStuff(); } on the class level is an initializer block. – amon May 12 '14 at 15:03
    
@SimonBarker The code block that is surrounding doStuff() – dirkk May 12 '14 at 15:03
2  
ayp-sd.blogspot.de/2012/12/… – gnat May 12 '14 at 15:13
1  
"[S]imply changing the order of code blocks will actually change the code." And how is that any different from changing the ordering of variable initializers or individual lines of code? If there are no dependencies, then no harm occurs, and if there are dependencies, then placing the dependencies out of order is the same as misordering dependencies for individual lines of code. Just because Java lets you refer to methods and classes before they are defined does not mean that order-dependent code is rare in Java. – JAB May 12 '14 at 19:37

There are two cases where I use initializer blocks.

The first one is for initializing final members. In Java, you can initialize a final member either inline with the declaration, or you can initialize it in the constructor. In a method, it is forbidden to assign to a final member.

This is valid:

final int val = 2;

This is valid too:

final int val;

MyClass() {
    val = 2;
}

This is invalid:

final int val;

MyClass() {
    init();
}

void init() {
    val = 2;  // cannot assign to 'final' field in a method
}

If you have multiple constructors, and if you can't initialize a final member inline (because the initialization logic is too complex), or if the constructors cannot call themselves, then you can either copy/paste the initialization code, or you can use an initializer block.

final int val;
final int squareVal;

MyClass(int v, String s) {
    this.val = v;
    this.s = s;
}

MyClass(Point p, long id) {
    this.val = p.x;
    this.id = id;
}

{
    squareVal = val * val;
}

The other use case I have for initializer blocks is for building small helper data structures. I declare a member, and put values in it right after its declarations in its own initializer block.

private Map<String, String> days = new HashMap<String, String>();
{
    days.put("mon", "monday");
    days.put("tue", "tuesday");
    days.put("wed", "wednesday");
    days.put("thu", "thursday");
    days.put("fri", "friday");
    days.put("sat", "saturday");
    days.put("sun", "sunday");
}
share|improve this answer
    
It's not the method call that is invalid. It's the code inside the init method that is invalid. Only constructors and initalizer blocks can assign to a final member variable, thus the assignment in init will not compile. – barjak Jun 26 at 20:49

In addition to the initialization of an instance variable that is declared as final (see barjak's answer), I would also mention static initialization block.

You can use them as kind of "static contructor".

That way you can do complex initializations on a static variable a the first time the class is referenced.

Here is an example inspired by barjak's one:

public class dayHelper(){
    private static Map<String, String> days = new HashMap<String, String>();
    static {
        days.put("mon", "monday");
        days.put("tue", "tuesday");
        days.put("wed", "wednesday");
        days.put("thu", "thursday");
        days.put("fri", "friday");
        days.put("sat", "saturday");
        days.put("sun", "sunday");
    }
    public static String getLongName(String shortName){
         return days.get(shortName);
    }
}
share|improve this answer

Confusing Syntax

Looking at this question, there are 3 answers, yet you fooled 4 people with this syntax. I was one of them and I've been writing Java for 16 years! Clearly, the syntax is potentially error prone! I'd stay away from it.

Telescoping Constructors

For really simple stuff, you can use "telescoping" constructors to avoid this confusion:

public class Test {
    private String something;

    // Default constructor does some things
    public Test() { doStuff(); }

    // Other constructors call the default constructor
    public Test(String s) {
        this(); // Call default constructor
        something = s;
    }
}

Builder Pattern

If you need to doStuff() at the end of each constructor or other sophisticated initialization, perhaps a builder pattern would be best. Josh Bloch lists several reasons why builders are a good idea. Builders take a little time to write, but properly written, they are a joy to use.

public class Test {
    // Value can be final (immutable)
    private final String something;

    // Private constructor.
    private Test(String s) { something = s; }

    // Static method to get a builder
    public static Builder builder() { return new Builder(); }

    // builder class accumulates values until a valid Test object can be created. 
    private static class Builder {
        private String tempSomething;
        public Builder something(String s) {
            tempSomething = s;
            return this;
        }
        // This is our factory method for a Test class.
        public Test build() {
            Test t = new Test(tempSomething);
            // Here we do your extra initialization after the
            // Test class has been created.
            doStuff();
            // Return a valid, potentially immutable Test object.
            return t;
        }
    }
}

// Now you can call:
Test t = Test.builder()
             .setString("Utini!")
             .build();

Static Initializer Loops

I used to use static initializers a lot, but occasionally ran into loops where 2 classes depended on each other's static initializer blocks being called before the class could be fully loaded. This produced a "failed to load class" or similarly vague error message. I had to compare files with the last known working version in source control in order to figure out what the problem was. No fun at all.

Lazy Initialization

Maybe static initializers are good for performance reasons when they work and aren't too confusing. But in general, I'm preferring lazy initialization to static initializers these days. It's clear what they do, I haven't run into a class-loading bug with them yet, and they work in more initialization situations than initializer blocks do.

Data Definition

Instead of static initialization for building data structures, (compare with examples in the other answers), I now use UncleJim's immutable data definition helper functions:

private ImMap<String,String> days =
        map(tup("mon", "monday"),
            tup("tue", "tuesday"),
            tup("wed", "wednesday"),
            tup("thu", "thursday"),
            tup("fri", "friday"),
            tup("sat", "saturday"),
            tup("sun", "sunday"));

Conculsion

In the beginning of Java, initializer blocks were the only way to do some things, but now they are confusing, error prone, and in most cases have been replaced by better alternatives (detailed above). It's interesting to know about initializer blocks in case you see them in legacy code, or they come up on a test, but if I were doing code review and I saw one in new code, I'd ask you to justify why none of the above alternatives were suitable before giving your code the thumbs-up.

share|improve this answer

As fas as non-static initializer blocks are concerned, their bare function is to act as a default constructor in anonymous classes. That is basically their only right to exist.

share|improve this answer

I totally agree with statements 1, 2, 3. I also never use block initializers for these reasons and I don't know why it exists in Java.

However, I'm forced to use the static block initializer in one case: when I have to instantiate a static field whose constructor can throws a checked exception.

private static final JAXBContext context = JAXBContext.newInstance(Foo.class); //doesn't compile

But instead you have to do:

private static JAXBContext context;
static {
    try
    {
        context = JAXBContext.newInstance(Foo.class);
    }
    catch (JAXBException e)
    {
        //seriously...
    }
}

I find this idiom very ugly (it also prevents you to mark context as final) but this is the only way supported by Java to initialize such fields.

share|improve this answer
    
I think if you set context = null; in your catch block, that you may be able to declare context as final. – GlenPeterson Jun 27 at 17:32
    
@GlenPeterson I tried but it doesn't compile: The final field context may already have been assigned – Spotted 2 days ago
    
oops! I bet you can make your context final if you introduce a local variable inside the static block: static { JAXBContext tempCtx = null; try { tempCtx = JAXBContext.newInstance(Foo.class); } catch (JAXBException ignored) { ; } context = tempCtx; } – GlenPeterson 2 days ago

protected by gnat Jun 27 at 13:52

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.