class Fu{
int j = 1;
Fu(){super();this.draw();}
void draw(){System.out.println("j "+j);}
}
class Zi extends Fu{
int i = 2;
Zi(){super();draw();}
void draw(){System.out.println("i "+i);}
public static void main(String[] args){
Zi z = new Zi();
}
}结果是: i 0
i 2 第一个 i 0 哪来的呢 ? 望高手指点
int j = 1;
Fu(){super();this.draw();}
void draw(){System.out.println("j "+j);}
}
class Zi extends Fu{
int i = 2;
Zi(){super();draw();}
void draw(){System.out.println("i "+i);}
public static void main(String[] args){
Zi z = new Zi();
}
}结果是: i 0
i 2 第一个 i 0 哪来的呢 ? 望高手指点
类Zi()中super(),然后是类Fu()中super(),此时初始化j=1,然后到Zi()中draw(),此时i,并没有初始化,默认为0,所以有输出i 0;子类对象的构造和初始化顺序总结为:
1.分配成员变量的存储空间并进行默认的初始化;
2.调用对象的构造函数,绑定构造函数的参数,所以初始化j=1;
3.如果对象构造函数中存在this调用,则调用相应重载的构造函数,重载的构造函数执行完后,回到当前构造函数,当前构造函数执行第5步
若没有this调用,执行步骤4;
4.显式或隐式地调用父类的构造函数,一直到object为止,父类的构造函数又开始执行第2步流程,父类的构造函数执行完毕后回到当前构造
函数继续执行;
5.对成员变量进行显式初始化;
6.执行构造函数中其它程序代码;
7.如果有初始化块,优先执行初始化块程序;
解决方法不要再构造函数中调用被继承的方法,最好不要调用任何方法,仅仅完成初始化作用
从这一点在来看这道题就很容易了:
子类构造方法首先调用父类构造方法——>
父类构造方法调用this.draw()(此时的draw其实还是子类的draw(),Overriding的原因,由于父类field中无i值,故取默认值0)——>
子类构造方法调用子类draw(),而子类field中能找到i=2。
因此,输出结果i=0,i=2另外,你在父类的draw()前面加final或者private,就会得到j=1,i=2了。