静态块、静态字段、实例初始化块、构造器,四种初始化机制混在一条继承链上,顺序到底怎么排,这篇真实创建两个Child实例,把完整的14步执行顺序原样记录下来。
上一篇:字段隐藏真实验证
Parent/Child 两层继承链,各自都有静态代码块、静态字段初始化、实例初始化块、构造器四种初始化机制,真实创建两个Child实例记录完整日志。
StaticInitOrderDemo.java class Parent { static { log.add("Parent 静态代码块"); } static String staticField = initStaticField(); // 调用中会log { log.add("Parent 实例初始化块"); } Parent() { log.add("Parent 构造器"); } } class Child extends Parent { /* 同样四件套 */ } new Child(); new Child();
1. main 开始,即将创建第一个 Child 实例 2. Parent 静态代码块 3. Parent 静态字段初始化 4. Child 静态代码块 5. Child 静态字段初始化 6. Parent 实例初始化块 7. Parent 构造器 8. Child 实例初始化块 9. Child 构造器 10. main 创建第二个 Child 实例 11. Parent 实例初始化块 12. Parent 构造器 13. Child 实例初始化块 14. Child 构造器
真实完整记录下的14步,清楚展示了两条独立的规则真实同时生效。
对比第2-5步和10步之后的日志,能直接看出静态初始化真实不会重复。
对比步骤6-9和步骤11-14,两组顺序完全相同,证明实例级别的初始化是每次创建对象都要走一遍的。
真实结果显示第一次和第二次创建 Child 实例,都真实完整走了"Parent 实例初始化块 → Parent 构造器 → Child 实例初始化块 → Child 构造器"这四步,顺序完全一致,没有任何跳过。这和静态初始化形成鲜明对比:实例初始化块和构造器绑定的是"每一个对象实例"的生命周期,而不是"类"本身的生命周期,所以每次 new 都真实是一次完整、独立的初始化过程。规则本身也印证了 系列前面验证过的类初始化时机:类的静态初始化被延迟到真正"首次主动使用"时才触发,且真实只触发一次;而构造器执行(伴随实例初始化块)则是每次实例化都会重新走一遍的独立过程。
对比第 2-5 步和第 10 步之后:第二次 new Child() 完全没有再出现"静态代码块"或"静态字段初始化",但实例初始化块和构造器又完整走了一遍——每一步都是真实运行时共享日志列表记录下的。