26

What is the rationale behind making this kind of code valid in java? Does it exist for some particular reason or is it just a byproduct of other Java language design decisions? Can't you just use the consructor to achieve the same effect?

class Student
{
    {
        System.out.println("Called when Student class is instantiated.");
    }
}
James P.
  • 19,313
  • 27
  • 97
  • 155

4 Answers4

48

One point is that it will execute whichever constructor is called. If you have several constructors and they don't call each other (for whatever reason, e.g. each wanting to call a directly-corresponding superclass constructor) this is one way of making sure the same code is executed for all constructors, without putting it in a method which could be called elsewhere.

It's also potentially useful when you're writing an anonymous class - you can't write a constructor, but you can write an initializer block. I've seen this used for JMock tests, for example.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    +1 for the anonymous class mention. Definitely my most frequent use for initializer blocks. – Matt Ball Mar 04 '11 at 16:26
  • I knew it wouldn't be long before Jon's answer would climb to the top. Upvoted for the mention of usage in an anonymous class. – James P. Mar 04 '11 at 16:29
  • 3
    Another good thing about initializer blocks: they can assign final instance fields. This is not possible with a function called from multiple constructors. – G_H Mar 04 '11 at 17:12
  • Did we need another reason not to use final? – Stephan Eggermont Mar 06 '11 at 13:41
  • 1
    @Stephan: Are you suggesting that immutability is a bad thing? I'm fond of making methods, classes and static/instance variables wherever possible... – Jon Skeet Mar 06 '11 at 17:44
  • I do consider that kind of immutability to be a bad thing, yes. I like having immutable instances, but have encountered too many finals that needed overriding. Design for reusability is difficult, there is no need to make it more difficult. – Stephan Eggermont Mar 07 '11 at 19:30
  • @Stephan: I think we'll have to agree to differ. I find it's much easier to design for composition via immutable types and simple interfaces than to try to design inheritance trees of mutable types and then somehow use them reliably. – Jon Skeet Mar 07 '11 at 19:50
  • The situation might have improved, but in early java (till 1.4 or so) I've never seen it used sensibly. But I tend to push things to the limits, and often need better implementations than are provided. String is the obvious example of too early binding. – Stephan Eggermont Mar 07 '11 at 21:56
  • @Stephan: So you'd make String mutable? Eek. As I say, I think we'll have to agree to differ. – Jon Skeet Mar 07 '11 at 22:24
  • The more severe early binding problem is that it should have been an interface instead of a class. – Stephan Eggermont Mar 09 '11 at 01:03
  • @Stephan: *Possibly*. (There's CharSequence now, but that's very limited.) I wonder what the performance implications would have been like though... – Jon Skeet Mar 09 '11 at 06:25
  • this means you can do "new ArrayList(){{add("one");}};" – Epaga Mar 09 '11 at 09:37
20

It's called an initializer 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.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • That's awesome. I knew about blocks but didn't know they could used for constructors. Thanks for the information. – James P. Mar 04 '11 at 16:26
5

It called init block. In such block you can perform logic that are same for all constructions also you can separate declaration and initialization of same fields.

upd and of course double brace initialization, like

List<Integer> answers = new ArrayList<Integer>(){{add(42);}}
Stan Kurilin
  • 15,614
  • 21
  • 81
  • 132
  • "Double brace initialization" is the same thing as what @Jon mentioned: using an initializer block in an anonymous class. – Matt Ball Mar 04 '11 at 16:32
5

This is an initialization block. As mentioned by Matt Ball, they are copied into each constructor.

You might be interested to know about static initialization blocks (also in Matt's link):

public class Foo {
    static {
        System.out.println("class Foo just got initialized!");
    }

    {
        System.out.println("an instance of Foo just got initialized!");
    }
}
Matthew
  • 44,826
  • 10
  • 98
  • 87