4

When I define a Java class:

class A {
   private String str = "init method 1";

   public A() {
       str = "init method 2";
   }
}

I can either init str when define it or init it in constructor. My question is what difference of the two methods is? Which method is preferred?

Thomash
  • 6,339
  • 1
  • 30
  • 50
TieDad
  • 9,143
  • 5
  • 32
  • 58
  • You are talking about instance members (class members would be `static`). Please note that there is no single correct answer for your question so the answers will be based on opinions. – Uwe Plonus Jul 24 '13 at 08:12
  • 1
    Also check this question: http://stackoverflow.com/questions/3918578/should-i-initialize-variable-within-constructor-or-outside-constructor – Yuri Jul 24 '13 at 08:12

4 Answers4

4

The initialization block values are assigned before constructor assigns them.

So the value init member 1 will be assigned first and then init member 2 will be assigned.

Consider this example from theJavaGeek

class InitBlocksDemo {

    private String name ;

    InitBlocksDemo(int x) {
        System.out.println("In 1 argument constructor, name = " + this.name);
    }

    InitBlocksDemo() {
        name = "prasad";
        System.out.println("In no argument constructor, name = " + this.name);

    }

    /* First static initialization block */
    static {
        System.out.println("In first static init block ");
    }

    /* First instance initialization block  */
    {
        System.out.println("In first instance init block, name = " + this.name);
    }

    /* Second instance initialization block */
    {
        System.out.println("In second instance init block, name = " + this.name);
    }

    /* Second static initialization block  */
    static {
        System.out.println("In second static int block ");
    }

    public static void main(String args[]) {
        new InitBlocksDemo();
        new InitBlocksDemo();
        new InitBlocksDemo(7);
    }

}

This outputs,

In first static init block
In second static int block
In first instance init block, name = null
In second instance init block, name = null
In no argument constructor, name = prasad
In first instance init block, name = null
In second instance init block, name = null
In no argument constructor, name = prasad
In first instance init block, name = null
In second instance init block, name = null
In 1 argument constructor, name = null

The program flows as follows.

  • When program starts executing, the class InitBlocksDemo is loaded into JVM.
  • Static initialization blocks run when class is loaded in the order they appear in the program.
  • Now when execution of static block completed, main method is encountered.
  • The statement new InitBlocksDemo(); causes the no-argument constructor to be invoked.
  • As there is a default call to the super no-argument constructor, control goes to super class i.e. Object class
  • After it has completed, then control comes back to our class and starts giving default values to instance variables. In this case, variable name will be assigned value as null.
  • Now the instance blocks will execute in the order they appear in the program. We have not re-assigned value to name variable yet so it will print null
  • After instance blocks are executed, then control goes to the constructor. Here name = "prasad"; will re-assign a new value hence “prasad” will get printed in the no-argument constructor
  • 9.The statement new InitBlocksDemo(7); causes the one-argument constructor to be invoked. Rest of the process is same. Only difference is that name is not re-assigned a new value hence it will print null
Prasad Kharkar
  • 13,410
  • 5
  • 37
  • 56
4

There is no difference between them, the compiler copies the initialization blocks to the constructors

If you, decompile the generated class file for the class

class A {
    private String str1 = "init method 1";

    private String str2;

    public A() {
        str2 = "init method 2";
    }

    public A(String str2) {
        str2 = str2;
    }
}

you can find

class A
{

    private String str1;
    private String str2;

    public A()
    {
        str1 = "init method 1";
        str2 = "init method 2";
    }

    public A(String str2)
    {
        str1 = "init method 1";
        str2 = str2;
    }
}
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
3

the difference is in when the assignation happens. fields are assigned const values before the constructor runs, so if you add this line to your constructor:

System.out.println(str);

you'll see that the old value is there before you assign the newer one in the constructor.

there's not a whole lot of difference except that, and which to use is mostly personal preference.

personally anythiong i can assign directly as part of the field declaration - thats what i do.

radai
  • 23,949
  • 10
  • 71
  • 115
1

In my personal experience, its all about how expensive or detailed the object initialization is. Secondly, you can also consider it as lazy creation vs active creation. I usually create objects at instance variable level if only constructor is involved. If there are further calls to initialize the member in question, then definitely the call will be moved to constructor or to a method where it needs to be initialized.

Thats why factory method pattern is used, to delegate the actual object creation to another class.

MayurB
  • 3,609
  • 2
  • 21
  • 36