Why instance block changes are not reflected when passing the changed value to constructor

I just came across a scenario, which i never experimented with before -

public class InstanceBlocks {
    public static  int i = 5;

    {
        i ++;
        System.out.println("Inside first instance block "+ i);
    }

    public InstanceBlocks(){
        this(i);
        i++;
        System.out.println("Inside def const "+ i); 
    }

    public InstanceBlocks(int i){
        i =i*2;
        System.out.println("Inside param const "+ i);
    }

}

The o/p is -

Inside first instance block 6
Inside param const 10
Inside def const 7

Why is the parameterized constructor printing 10? The 'this' call is passing the value as 5, but isn't the value of i already changed before the 'this' call?

Jon Skeet
people
quotationmark

The order of execution here is:

  • Evaluation of i inside this(i) (i is still 5 at this point)
  • Object constructor
  • Instance initializer (the block that increments i from 5 to 6)
  • Execution of the body of the InstanceBlocks(int) constructor (the parameter has a value of 5 because of the first step, and note that the i = i * 2 is modifying the parameter, not the field)
  • Execution of the rest of the body of the InstanceBlocks() constructor

This is documented in JLS 12.5.

The instance initializer is only executed once, because only one instance is being constructed.

To answer your specific question:

The 'this' call is passing the value as 5, but isn't the value of i already changed before the 'this' call?

And the answer is "no, because the chained constructor arguments are evaluated before the instance initializer is called".

people

See more on this question at Stackoverflow