静态域/域的初始化、静态代码块/构造代码块的实行、构造方法的调用 顺序
这5者的先后顺序中,有些顺序是跟Java源代码顺序有关的,有些无关的。
首先应该定义两个类,用于代表两种域的类型,这两个类的构造方法会打印信息,用于指示自身被实例化了。
class Field { public Field(int i) { System.out.println("B: 域引用第 " + i + " 次实例化"); } } class StaticField { public StaticField(int i) { System.out.println("A: 静态域引用第 " + i + " 次实例化"); } }
1:静态的“东西”一定是比非静态的先执行的。
public class InitOrderTest { public static void main(String[] args) { Body b = new Body(); } } class Body { // B { System.out.println("B: 构造代码块第1次"); } Field f1 = new Field(1); { System.out.println("B: 构造代码块第2次"); } { System.out.println("B: 构造代码块第3次"); } Field f2 = new Field(2); // A static { System.out.println("A: 静态代码块第1次"); } static StaticField sf1 = new StaticField(1); static { System.out.println("A: 静态代码块第2次"); } static { System.out.println("A: 静态代码块第3次"); } static StaticField sf2 = new StaticField(2); // C public Body() { System.out.println("C: 构造方法"); } }
A: 静态代码块第1次 A: 静态域引用第 1 次实例化 A: 静态代码块第2次 A: 静态代码块第3次 A: 静态域引用第 2 次实例化 B: 构造代码块第1次 B: 域引用第 1 次实例化 B: 构造代码块第2次 B: 构造代码块第3次 B: 域引用第 2 次实例化 C: 构造方法
即便Body类的B代码片段写在A片段前面,打印结果A还是在B前面,因为类需要先加载才能实例化,静态域和静态代码块会在类生命周期的“初始化”步骤中进行处理。
静态域和静态代码块算是“类"层次,域和构造代码块算是“对象”层次,同一层次的域和代码块顺序先后跟代码顺序一致,不存在一定是谁先处理的情况。
class Body { // B { System.out.println("B: 构造代码块第1次"); } { System.out.println("B: 构造代码块第2次"); } Field f1 = new Field(1); { System.out.println("B: 构造代码块第3次"); } Field f2 = new Field(2); // A static { System.out.println("A: 静态代码块第1次"); } static { System.out.println("A: 静态代码块第2次"); } static StaticField sf1 = new StaticField(1); static { System.out.println("A: 静态代码块第3次"); } static StaticField sf2 = new StaticField(2); // C public Body() { System.out.println("C: 构造方法"); } }
A: 静态代码块第1次 A: 静态代码块第2次 A: 静态域引用第 1 次实例化 A: 静态代码块第3次 A: 静态域引用第 2 次实例化 B: 构造代码块第1次 B: 构造代码块第2次 B: 域引用第 1 次实例化 B: 构造代码块第3次 B: 域引用第 2 次实例化 C: 构造方法
构造方法是这5者中最后执行的
class Body { // C public Body() { System.out.println("C: 构造方法"); } // B { System.out.println("B: 构造代码块第1次"); } Field f1 = new Field(1); { System.out.println("B: 构造代码块第2次"); } { System.out.println("B: 构造代码块第3次"); } Field f2 = new Field(2); // A static { System.out.println("A: 静态代码块第1次"); } static StaticField sf1 = new StaticField(1); static { System.out.println("A: 静态代码块第2次"); } static { System.out.println("A: 静态代码块第3次"); } static StaticField sf2 = new StaticField(2); }
A: 静态代码块第1次 A: 静态域引用第 1 次实例化 A: 静态代码块第2次 A: 静态代码块第3次 A: 静态域引用第 2 次实例化 B: 构造代码块第1次 B: 域引用第 1 次实例化 B: 构造代码块第2次 B: 构造代码块第3次 B: 域引用第 2 次实例化 C: 构造方法