变量、初始化块和构造方法的初始化顺序问题(笔试题)
在某公司面试时碰见的该题目,
给出如下程序,让写出程序打印的语句的顺序,也就是程序加载执行的过程。
当时确实有些懵了,只根据大体印象写了答案。回来后写程序跑了一遍,自己还真是没猜对。所以贴出来帮助记忆并与大家共赏!!
package com.skd.timu; public class Demo4 { public static void main(String[] args) { new childrenDemo(); new childrenDemo(); } } class ParentDemo{ static String staParentString="父类-静态-变量"; String parentString="父类-非静态-变量"; static{ System.out.println(staParentString); System.out.println("父类 - 静态 - 初始化块"); } { System.out.println(parentString); System.out.println("父类 - 非静态 - 初始化块"); } ParentDemo(){ System.out.println("父类-构造方法"); } } class childrenDemo extends ParentDemo{ static String staChildrenString="子类-静态-变量"; String childrenString="子类-非静态-变量"; static{ System.out.println(staChildrenString); System.out.println("子类 - 静态 - 初始化块"); } { System.out.println(childrenString); System.out.println("子类- 非静态 - 初始化块"); } childrenDemo(){ System.out.println("子类-构造方法"); } }
看完该程序不妨自己先写个输出语句的顺序然后写程序执行看是否与自己的判断一致。
先把程序执行的结果贴上:
父类-静态-变量 父类 - 静态 - 初始化块 子类-静态-变量 子类 - 静态 - 初始化块 父类-非静态-变量 父类 - 非静态 - 初始化块 父类-构造方法 子类-非静态-变量 子类- 非静态 - 初始化块 子类-构造方法 父类-非静态-变量 父类 - 非静态 - 初始化块 父类-构造方法 子类-非静态-变量 子类- 非静态 - 初始化块 子类-构造方法
构造块的加载顺序在静态块之后但在构造方法之前,而且在构造块加载之前,变量已经加载;
构造方法是在静态变量,静态块,变量,构造块后才加载的,是在类实例化时,除了调用方法外的最后加载的位置;
因为静态变量和静态块都是全局的,因此在程序加载时就已经加载,不会因为是子类中的静态变量和静态块就比父类的构造块加载晚,但在都是静态变量或静态块的情况下,
总是先初始化父类的,然后初始化子类的。
同样的因为构造块和构造方法不是全局的,而且子类在实例化时总是先调用父类的构造块和构造方法,因此父类的构造块和构造方法在子类的之前调用。即在实例化子类时,程序会先调用父类的实例化构造块或者构造方法,然后才会调用子类的构造块和构造方法完成子类的实例化。
而且,构造块和构造方法会在每次实例化的时候都执行,静态变量和静态块只会执行一次(不管该类实例化多少对象)。