
深入探讨Java继承中的构造器与变量初始化顺序
Java继承机制中,构造器和变量的初始化顺序并非总是直观易懂。虽然《On Java》提到变量会在任何方法(包括构造器)调用前初始化,但JVM的实际执行顺序可能出乎意料。
让我们通过一个简化示例来分析:
class Shape {
Shape() {
System.out.println("Shape");
}
}
class Line extends Shape {
Line() {
super();
System.out.println("Line");
}
}
public class CADSystem extends Shape {
private Line li = new Line(); // 关键点:成员变量初始化
public CADSystem() {
super();
System.out.println("CADSystem");
}
}
运行结果:
立即学习“Java免费学习笔记(深入)”;
Shape Shape Line CADSystem
很多人会误以为执行顺序是:
- 创建
Line对象,调用Line构造器,输出"Shape"、"Line"。 - 调用
CADSystem构造器,在li初始化前输出"Shape"。 - 输出"CADSystem"。
然而,JVM的实际执行顺序遵循以下规则:
-
父类初始化优先: 首先,
CADSystem继承自Shape,因此JVM会先初始化Shape类,输出"Shape"。 -
成员变量初始化: 接下来,JVM初始化
CADSystem的成员变量li。这会调用Line的构造器。 -
super()调用:Line构造器中包含super(),这会在Line构造器体执行前调用父类Shape的构造器,再次输出"Shape"。 -
Line构造器体执行: 然后,Line构造器体执行,输出"Line"。 -
CADSystem构造器执行: 最后,CADSystem构造器执行,输出"CADSystem"。
因此,理解的关键在于:父类构造器的调用发生在子类成员变量初始化之前,而super()的调用发生在子类构造器体之前。 这决定了最终的执行顺序。 成员变量的初始化并非简单的在构造器之前,而是与父类构造器的调用顺序紧密相连。










