87

In other words, why would you need an instance initializer? What difference or advantage do you have in writing a instance initializer over a constructor?

Ajay
  • 7,378
  • 18
  • 57
  • 75

7 Answers7

112

This seems to explain it well:

Instance initializers are a useful alternative to instance variable initializers whenever:

  • initializer code must catch exceptions, or

  • perform fancy calculations that can't be expressed with an instance variable initializer. You could, of course, always write such code in constructors.

But in a class that had multiple constructors, you would have to repeat the code in each constructor. With an instance initializer, you can just write the code once, and it will be executed no matter what constructor is used to create the object. Instance initializers are also useful in anonymous inner classes, which can't declare any constructors at all.

From: JavaWorld Object initialization in Java.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
javamonkey79
  • 17,443
  • 36
  • 114
  • 172
  • 19
    On the other hand you can write code once in one constructor and just call it from all other constructors. But anonymous inner classes make a good point. – Tadeusz Kopec for Ukraine Aug 31 '09 at 14:03
  • 11
    You can call it from other constructors - but then you are again repeating the call. If you add a new constructor, you have to remember to add the call to it. Not so with an instance initializer. – talonx May 22 '10 at 13:37
  • 5
    @talonx, I do agree with your argument about forgetting, but utilizing default behavior is equally dangerous. When a supporter is reading through a constructor in legacy code, one wouldn't always remember to check for possible instance initializers. Whereas an explicitly used init() will stand out. – Assambar Sep 15 '11 at 16:20
  • 1
    @javamonkey79: Are you saying that if I pick _constructor_ over _instance initializer_ for my class, the only place where instance initializer is useful is when working with anonymous classes? – realPK Feb 23 '14 at 17:11
  • 5
    @Assambar You cannot assign final fields in your init() method, but you can in an initializer block. – Timmos Apr 04 '14 at 08:27
  • @talonx, Having to manually add a call to `init()` in a new constructor is actually an advantage, not a disadvantage. Having an **automatic** call to "init" is actually pretty dangerous and may lead to bugs. – Pacerier Sep 22 '14 at 14:33
  • @Pacerier Please give an example. – talonx Oct 17 '14 at 09:56
  • @talonx, An example is when you need a new constructor which doesn't use the instance initializer. Now you create that constructor verify it's contents from `{` to `}` and happily walk away thinking that you are done, except there's an invisible call to the instance initializer which screws up the program at runtime. – Pacerier Oct 17 '14 at 18:52
  • 1
    @Pacerier It's very unlikely that you would want a constructor which does _not_ call the instance initializer. It would indicate something that can be improved in the design, to me. – talonx Oct 18 '14 at 15:16
  • @talonx, It's in fact very likely when you are in the refactoring phase 1 year after the original author had coded the app. – Pacerier Oct 19 '14 at 18:37
  • 1
    @Pacerier I guess I was not clear in what I tried to convey. My point was that if you want a new constructor, now or in the future, that does not need the instance initializer, then that constructor is potentially creating a "different" kind of object. And that, is a code smell. – talonx Oct 20 '14 at 08:23
  • @talonx, That's called refactoring, someone else restructuring your code to fit new requirements. Code after all is not maintained by one person, but will be passed on to other people in the future. – Pacerier Oct 20 '14 at 09:39
  • @Pacerier I am referring to good Java design. I know what refactoring is. – talonx Oct 20 '14 at 14:57
  • @talonx, And I know you know what refactoring is. I'm saying that that's called refactoring, not called "code smell". – Pacerier Oct 20 '14 at 16:07
  • @Pacerier We are talking about different things. – talonx Oct 27 '14 at 17:41
  • @talonx, We aren't. You claim that "potentially creating a different kind of object" is a code smell, but it's part and parcel of refactoring. Code does not stay the same but slowly transforms to fit new requirements. – Pacerier Oct 27 '14 at 19:16
  • @Pacerier "Code does not stay the same but slowly transforms to fit new requirements." - Sure. I have to disagree here as introducing a way to create a different kind of object would mean you are breaking the original design, and thus, is a code smell. Refactoring need not always lead to "good" things. – talonx Oct 28 '14 at 06:13
  • @talonx, We are breaking the original design because it no longer fits our purpose. Either it gets thrown away or it slowly gets refactored into a new design. – Pacerier Oct 29 '14 at 05:10
  • @Pacerier Fair enough. Rephrasing what I was trying to say - Refactoring with a purpose is "good". Refactoring without understanding the original design usually leads to "bad" things. – talonx Oct 31 '14 at 10:46
22

In terms of object lifecycle, there is no difference. Both are invoked at construction time, and logically the initializer block can be considered part of construction.

Semantically, an initializer is a nice tool to have for several reasons:

the initializer can improve code readability by keeping the initialization logic next to the variable being initialized:

   public class Universe {
       public int theAnswer;
       {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;
       }

       // a bunch of other vars
   }

vs

   public class Universe {
       public int theAnswer;

       // a bunch of other vars

       public Universe() {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;

         // other constructor logic
       }
   }

Initializers are invoked regardless of which constructor is used.

Initializers can be used in anonymous inner classes, where constructors can't.

ykaganovich
  • 14,736
  • 8
  • 59
  • 96
  • 3
    What you have their is technically an "instance variable initialiser" not an "instance initialiser" (a block directly nested within a class). See JLS 3rd section 8.6. – Tom Hawtin - tackline Aug 31 '09 at 05:42
  • Instance initializer block doesn't have a name as shown [here](http://www.javatpoint.com/instance-initializer-block). Isn't it? You have marked your instance initializer code with name `theAnswer`. Is that correct? or I'm missing something. – RBT Dec 27 '16 at 01:22
  • 1
    @RBT `theAnswer` is a declared instance variable. It is initialized in an anonymous initializer block. Note the semicolon after the variable declaration. – ykaganovich Dec 29 '16 at 22:28
12

When you have many constructors and want some common code to be executed for each constructor you can use instance initializer.As it is called for all constructors.

Rahul Garg
  • 8,410
  • 8
  • 33
  • 28
4

I would avoid the instance initializer idiom in general - the only real advantage it gives over variable initializers is exception handling.

And since an init method (callable from constructor) can also do exception handling and also centralizes constructor setup code, but has the advantage that it can operate on constructor parameter values, I'd say that the instance initializer is redundant, and therefore to be avoided.

CPerkins
  • 8,968
  • 3
  • 34
  • 47
  • 1
    You would have to call manually the init method in ALL your constructors. – Stephan Oct 28 '13 at 17:31
  • 2
    @Alex Good point, but since most classes with multiple constructors have common logic, they tend to call each other anyway. At least in most of my classes. – CPerkins Oct 29 '13 at 13:35
4

The real advantage of instance initializers over constructors is seen when we use an anonymous inner class.

Anonymous inner classes can't have a constructor (as they're anonymous), so they're a pretty natural fit for instance initializers.

padippist
  • 1,178
  • 1
  • 16
  • 30
1

At the time of object creation, if we want to perform initialise of instance variables, then we should go for Constructor, other than initialisation activity if we want to perform any activity at the time of object creation then we should go for instance block.

We can't replace constructor with instance block because constructor can take argument but instance block can't take arguments.

We can't replace instance block wih constructor because a class can contain more than one constructor. If we want to replace instance block with constructor then in every constructor we have to write instance block code because at runtime which constructor will be called we can't expect, this will unnecesarily increase duplicate code.

Example :

class MyClass{

    static int object_count = 0;

    MyClass(){
        object_count++;
    }

    MyClass(int i){

        object_count++;
    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

Output : 2

class MyClass{

    static int object_count = 0;

    {
        object_count++;
    }

    MyClass(){

    }

    MyClass(int i){     

    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

Output : 2

NPE
  • 432
  • 5
  • 13
0

Initializer is way to share code between constructors and it make code more readable if initializer is used with variable declaration.

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

dnyanesh
  • 101
  • 1
  • 6