package org.hhb.objectinit;
class Father {
static {
System.out.println("Father static block!");
}
public Father() {
System.out.println(this);
System.out.println(((Sub) this).a);
}
}
/**
*
* @author hehaibo
*
*/
public class Sub extends Father {
static {
System.out.println("Sub static block!");
}
public int a = 100;
public Sub() {
super();
System.out.println(this);
System.out.println(a);
a = 200;
}
public static void main(String[] args) {
System.out.println(new Sub().a);
}
}
输出结果:
1 Father static block!
2 Sub static block!
3 Father this object::org.hhb.objectinit.Sub@19ee1ac
4 0
5 Sub this object::org.hhb.objectinit.Sub@19ee1ac
6 100
7 200
对象初始化的顺序:
1 为Sub对象分配内存空间,
初始化Sub对象的成员变量的默认值,而不是 a=100。
2 调用Father类的构造函数,并且初始化Father成员变量的默认值
3 调用Object类的构造函数,由jvm负责。
4 打印第3行的输出结果我们可以看出,当前父类的构造函数的this就是Sub对象的引用地址,
可以证明1是正确的。
5 第4行输出的值是0,我们可以看出Sub对象初始化的时候成员变量的默认值。
6 父类的构造函数调用完后,再次将Sub对象的a成员变量的默认初始值修改为100,所以第6行打印输出是100。
7 再次执行a=200,main方法中输出200
得出的结论是:构建子类对象的时候,所有的成员变量都是默认值,
而子类的成员变量的非默认值初始化[也就是a=100]是在父类执行完成后才执行的。
参考:http://kenwublog.com/a-interesting-problem-about-java-object-init-order