Reputation: 31
I raised an issue at work, and simplified the code to reproduce it
public class Test {
public void callTest(){ return; }
public Test() { callTest(); }
}
public class Test1 extends Test{
private Integer myInt;
private Integer myNullInt = null;
public Test1() {
super();
}
@Override
public void callTest() {
myInt = 25;
myNullInt = 30;
}
@Override
public String toString() {
return "Test1{myInt=" + myInt + ", myNullInt=" + myNullInt +'}';
}
public static void main(String[] args) {
Test1 t1 = new Test1();
System.out.println(t1);
}
}
With this a a result : Test1{myInt=25, myNullInt=null}
On my understanding, instance variable initializers should be executed after the call to super(). So why is 'myInt' getting a value. And even how can it be possible ?
Upvotes: 2
Views: 142
Reputation: 21435
Instance initializers are executed after the call to super();
- that is why myNullInt
is null. For myInt
there is no instance initialzer involved.
The sequence of events is this:
new Test1()
objectTest1
is calledsuper
constructor Test()
Test
calls the callTest();
methodTest1
object, the callTest
method from Test1
is calledTest1.callTest()
sets the myInt
field to 25, the myNullInt
field to 30Test
endsTest1
resumes and executes the field initializer myNullInt = null;
myInt
doesn't have an initializer, its value is not changedThe process (including initialization with default values) is described in detail in the Java Language Specification, Creation of New Class Instances:
Whenever a new class instance is created, memory space is allocated for it with room for all the instance variables declared in the class type and all the instance variables declared in each superclass of the class type, including all the instance variables that may be hidden (§8.3).
[If there is not sufficient space ...] Otherwise, all the instance variables in the new object, including those declared in superclasses, are initialized to their default values (§4.12.5).
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
- / 2. [...]
- [...] an explicit or implicit invocation of a superclass constructor [...]
- Execute the instance initializers and instance variable initializers for this class [...]
- Execute the rest of the body of this constructor. [...]
Upvotes: 4
Reputation: 3400
The order of execution in your code looks like this.
Test1
is called.super
invokes the constructor in Test
.Test1
, the overridden callTest
is called, which sets the value for myInt
to 25 and myNullInt
to 30.super
is completed, now proceeds to create the Test1
object.myNullInt
is overwritten to null. Since there is no instruction for myInt
, the value is unchanged.sysout
call invokes the toString
and prints the Test1
value.The way instance variables are declared matters in inheritance.
Upvotes: 4