综合网上的相关帖子和我自己的调试,研究了一下关于JAVA继承类的静态变量、成员变量、父子类构造方法调用顺序问题。首先看一段程序:
class X {
Y b =new Y();//7、这里是父类成员变量初始化
static Y sb=new Y();//1、父类静态变量,输出static Y(静态代码块先初始化),2、Y
static{
System.out.println("static X父类静态代码块");//3、执行静态代码块
new Y();//4、这里只是输出Y,有static Y(静态代码块只执行一次)
}
X() {
System.out.println("X");//8、父类成员变量初始化之后,执行父类构造器输出X
}
}
class Y {
static{
System.out.println("static Y");
}
Y() {//执行构造函数
//这里有个super()==Object()
System.out.println("Y");
}
}
publicclass Z extends X {
finalstaticint mead=45;
finalbyte b=16;
static Y sb=new Y();//5、子类的静态变量,输出Y
static{
System.out.println("static Z");//6、子类的静态代码块
}
Y y =new Y();//9、这里是子类成员变量初始化
Z() {
//这里有super()==new X()
this.y =null;
System.out.println("Z");//10、子类成员变量初始化之后,执行子类构造器输出Z
}
publicstaticvoid main(String[] args) {
new Z();
}
}
执行结果:
static Y
Y
static X父类静态代码块
Y
Y
static Z
Y
X
Y
Z
解释:
static的东西在编译的时候就向内存要到了存取空间,他们的初始化要早于非static,顺序是先父类再子类。
初始化类,先执行super()父类的的构造函数(final和static之后),父类的构造函数先执行super()直到object super(),完了执行一般成员变量的初始化
一般成员变量初始化完毕,执行构造器里面的代码(super()之后的代码).
父类的初始化完成后(子类构造器里面super执行完毕),才轮到子类的成员变量初始化
子类成员变量初始化完毕,开始执行子类构造器里面的代码(super()之后的代码).
注意:
静态块和静态变量的调用顺序是按照书写顺序执行的,比如上边X类中静态块和静态变量的书写顺序颠倒如下:
class X {
Y b = new Y();
static{
System.out.println("static X父类静态代码块");
new Y();
}
static Y sb= new Y();
X() {
System.out.println("X");
}
}
则执行结果为:
static X父类静态代码块
static Y
Y
Y
Y
static Z
Y
X
Y
Z
最后:
确定变量空间和初始化赋值是分开进行的,先一次性确定静态成员变量空间 并赋给二进制0 ,然后按照书写顺序逐一赋值
如下代码,输出结果是0.0
publicclass Test {
staticint i=f();
staticdouble d=0.1234;
publicstaticvoid main(String[] args) {
new Test();
}
staticint f(){
System.out.println(d);
return3;
}
}
原址: