黑马程序员技术交流社区
标题:
探讨构造方法与构造代码块的执行顺序
[打印本页]
作者:
布德鸟
时间:
2016-5-8 16:50
标题:
探讨构造方法与构造代码块的执行顺序
本帖最后由 布德鸟 于 2016-5-8 18:11 编辑
在看java基础视频时被告知:构造代码块在构造方法前执行(下文称为“定理A”)
但是在学到继承时,我仿佛察觉到了点问题,看以下代码:
class Test_Extend {
public static void main(String[] args) {
Son s = new Son();
}
}
class Father
{System.out.println("Father的构造代码块");}
public Father(){
System.out.println("Father的构造方法");
}
}
class Son extends Father{
{System.out.println("Son的构造代码块");}
public Son(){
System.out.println("Son的构造方法");
}
}
运行输出:
Father的构造代码块
Father的构造方法
Son的构造代码块
Son的构造方法
根据输出结果好似得出跟“定理A”一样的结论:构造代码块在构造方法前执行,且先执行父类后执行子类。
但是,实际上这样理解不准确,我们先看子类的构造方法:
public Son(){
super(); //这段代码是必须的,即使我们不写,java编译时会自动加上的
System.out.println("Son的构造方法");
}
super(); 是调用父类的构造方法,这里证明了父类构造方法由子类构造方法调用,
执行顺序:子类构造方法 > 父类构造方法
,但因为super();是子类构造中第一个执行的语句,所以才有看似先执行父类构造方法的效果。
接着我们看一下输出结果:“Father的构造方法”先于“Son的构造代码块”,说明了
执行顺序:父类构造方法 > 子类构造代码块
,结合上面的
执行顺序:子类构造方法 > 父类构造方法
,得出
执行顺序:子类构造方法 > 子类构造代码块
那么问题来了既然
执行顺序:
子类构造方法 > 子类构造代码块
,那如何保证输出结果“Son的构造代码块”先于“Son的构造方法”?
其实也不难,以下是我的猜想:
与子类构造方法调用父类构造方法的效果一样,在构造方法内部的最顶端添加调用执行构造代码块的语句,如下:
public Son(){
super(); //这段代码是必须的,即使我们不写,java编译时会自动加上的
"执行本类构造代码块的语句"; //这段代码也是系统自动添加的,这段代码需要在排在super();下,因为要保证父类的先执行。
System.out.println("Son的构造方法");
}
这样子就能保证输出结果“Son的构造代码块”先于“Son的构造方法”了。
然后由个体试推整体的规律:在每个类的构造方法中的最顶端,不仅隐含着super();这个语句,还隐含着"执行本类构造代码块的语句";(下文称“定理B”)
然后我们把隐含代码显示如下:
class Test_Extend {
public static void main(String[] args) {
Son s = new Son();
}
}
class Father
{System.out.println("Father的构造代码块");}
public Father(){
super();
“执行本类构造代码块的语句”;
System.out.println("Father的构造方法");
}
}
class Son extends Father{
{System.out.println("Son的构造代码块");}
public Son(){
super();
"执行本类构造代码块的语句";
System.out.println("Son的构造方法");
}
}
然后一切都说的通了,我们来梳理一下执行过程:
①main方法里new一个Son对象
②Son类的构造方法Son()开始执行,super();调用父类的构造方法Father()
③Father()中的super();调用Object类的构造方法(Object类的构造方法内的执行过程略过)
④Father()中的"执行本类构造代码块的语句";调用Father类的构造代码块{System.out.println("Father的构造代码块");},输出
“Father的构造代码块”
⑤Father()中的System.out.println("Father的构造方法");执行,输出
"Father的构造方法"
⑤Son()中的"执行本类构造代码块的语句";调用Son类的构造代码块{System.out.println("Son的构造代码块");},输出
“Son的构造代码块”
⑥Son()中的System.out.println("Son的构造方法");执行,输出
"Son的构造方法"
推导的输出结果与实际结果不谋而合,本例的
执行顺序应该是:子类的构造方法 > 父类的构造方法 > 父类的构造代码块 > 子类的构造代码块
所以我推荐大家用
“定理B”(我目前没找到权威的资料证实,不过比较符合实际):在每个类(除了Object)的构造方法中的最顶端,不仅隐含着super();这个语句,还隐含着"执行本类构造代码块的语句";
构造代码块不是单纯的先于构造方法执行,而是在构造方法中会首先执行的一批调用语句,(调用语句有super();、
"执行本类构造代码块的语句";
等,且super();先于"执行本类构造代码块的语句";
)。
最后,祝各位的母亲,节日快乐!~
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2