In general, do not use non-static initializer blocks (and maybe avoid static ones too).
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 Paguro'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.
{ doStuff(); }
on the class level is an initializer block.doStuff()