构造器的调用顺序 2016.12.8
复杂对象调用构造器遵照下面的顺序:
(1)调用基类构造器。这个步骤会不断地反复递归下去,首先是构造这种层次结构的额根,然后是下一层的导出类,直到最低层的导出类。
(2)按声明顺序调用成员的初始化方法。
(3)调用导出类构造器的主体。
下面这个例子就形象地说明了构造器的调用顺序。
Meal类:
package cn.qdu.exercise10;
class Meal {
Meal(){
System.out.println("Meal()");
}
}
Bread类:
package cn.qdu.exercise10;
class Bread {
Bread(){
System.out.println("Bread()");
}
}
cheese类:
package cn.qdu.exercise10;
class Cheese {
Cheese(){
System.out.println("Cheese()");
}
}
lettuce类:
package cn.qdu.exercise10;
class Lettuce {
Lettuce(){
System.out.println("Lettuce()");
}
}
Lunch类继承Meal类:
package cn.qdu.exercise10;
class Lunch extends Meal {
Lunch(){
System.out.println("Lunch()");
}
}
protableLunch类继承lunch类:
package cn.qdu.exercise10;
class ProtableLunch extends Lunch {
ProtableLunch(){
System.out.println("ProtableLunch()");
}
}
Sandwich类继承ProtableLunch类,它反映了三层继承。
package cn.qdu.exercise10;
public class Sandwich extends ProtableLunch {
private Bread b=new Bread();
private Cheese c=new Cheese();
private Lettuce l=new Lettuce();
public Sandwich(){
System.out.println("Sandwich()");
}
public static void main(String[] args) {
new Sandwich();
}
}
运行结果:
Meal()
Lunch()
ProtableLunch()
Bread()
Cheese()
Lettuce()
Sandwich()
分析:
先调用基类的构造器,再输出调用成员的构造方法,最后再执行Sandwich方法的主体。
同时在此发现了一个问题,构造方法本身没有返回值,不能加void,一旦加了void,那么构造方法就变成了普通方法,也无法被实例化。
例如:若在Bread类的构造方法前面加void,则在Sandwich.java中将无法对其实例化。
package cn.qdu.exercise10;
class Bread {
void Bread(){
System.out.println("Bread()");
}
}
运行结果:
Meal()
Lunch()
ProtableLunch()
Cheese()
Lettuce()
Pickle()
Sandwich()
可见运行结果中没有出现Bread的实例化。