3

I know that Initialization blocks run when the class is first loaded (a static initialization block) or when an instance is created (an instance initialization block).

class SmallInit {
   static int x;
   int y;
   static { x = 7 ; } // static init block
   { y = 8; } // instance init block
}

But what is the special benefit of this, when we can do it like this:

class SmallInit {
   static int x = 7;
   int y = 8;
}
Bhushan
  • 18,329
  • 31
  • 104
  • 137

6 Answers6

7

One nice thing about instance initialization blocks is that they make the Double Brace Initialization pattern possible.

Instead of this:

Set<String> names = new HashSet<String>();
names.add("Peter");
names.add("Paul");
names.add("Mary");

You can do this:

Set<String> names = new HashSet<String>() {{
    add("Peter");
    add("Paul");
    add("Mary");
}};

The first brace creates an anonymous inner class; the second starts the instance initializer block. (Note that this means names is an instance of an anonymous subclass of HashSet, but that's often not an issue. This also means that this pattern only works for non-final classes.)

This is especially useful in one-off situations where it would be convenient to initialize an object as an expression. For example:

doSomethingToSet(new HashSet<String>() {{
    add("Peter");
    add("Paul");
    add("Mary");
}});
Wayne
  • 59,728
  • 15
  • 131
  • 126
  • Be careful with this - it absolutely works, but it creates an inner class, which has an implicit reference to 'this'. This can cause some interesting GC behavior if you aren't expecting it... I'm not saying don't use it (I certainly do), but be aware. – Kevin Day Dec 12 '11 at 03:40
  • @KevinDay Can you elaborate? I'm interested in what potential issues could arise. – Craig Otis Dec 12 '11 at 12:07
  • Sure - if you intialize a map like this, it winds up with an implicit reference to the outer object. If you then pass that map out to another area of your application, the 'outer object' will not be freed until the map itself is also freed. If the map is purely an implementation to the object, then this is fine. But if you expose the map in an external interface, it opens you up to unexpected references like this. – Kevin Day Dec 27 '11 at 16:27
3

I don't see any special benefit to static blocks that just contain one-line variable declarations. In fact, when all you're doing is assigning values to your class or instance variables, it is (in my opinion) more difficult to understand what's going on.

Static and instance blocks do come in handy, however, when you have more complicated starting states that need to be built up. Here's an example where both declaration and a static block are used:

static List<Sprocket> mySprockets = new ArrayList<Sprocket>();

static {
    mySprockets.add(new Sprocket("foo", 17));
    mySprockets.add(new Sprocket("bar", 8));
}
Craig Otis
  • 31,257
  • 32
  • 136
  • 234
2

I've used initialization blocks to populate complex data structures in the past. However, I've come to feel that writing a static function that populates the data structure and calling it is a better way to go.

e.g.

private static Map foo = initFoo();

private static Map initFoo() {
  Map foo = new Map();
  foo.put("x", "y");
  foo.put("a", "b");
  return foo;
}

There are people who aren't familiar with initializer blocks, for instance, and if you decide that you want your init code to be used in some other context, then you can easily just call the function.

BillRobertson42
  • 12,602
  • 4
  • 40
  • 57
0

There is no special benefit, it can help readability in certain cases (usually when you're declaring more than one member).

David Titarenco
  • 32,662
  • 13
  • 66
  • 111
0

The following could be an advantage of instance initialization block:

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

Go here for good overview.

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
0
  1. Without an initializer, the variable will be initialized to 0 or null. Therefore if you are going to set something in the constructor to other value, you are in effect setting it twice (once to 0 or null, then again in constructor to what you want). The performance penalty is negligible in vast majority of cases (an exception might be a math class that you use in a tight loop, but even this will be very dependent on what else happens in that loop).
  2. It can help with readibility.
  3. If you call a virtual method from constructor, a data member of derived class used in the overridden virtual method will have 0 or null as value unless it has initializer. I'm not 100% this is the case in Java as it has been a while; I know it is in C#.
Oliver
  • 27,510
  • 9
  • 72
  • 103