静态代码块、非静态代码块及构造器的执行顺序
-
第1步:类加载
① main()方法作为程序的主进口,当main方法运行时,不会先执行main方法中的代码,而是首先进行类的加载,包括本类与对应父类的加载。
② 类加载时,静态代码块、静态属性、静态方法都会被同时加载
③ 加载时,静态代码块会同时执行,先执行父类的静态代码块,再执行子类(本类)的静态代码块
④ 加载过后,可以在main方法中不需要实例化对象,就可以马上直接调用类中的静态属性和静态方法 -
第2步:执行main方法中的第一行代码
-
第3步:类实例化为对象
① 实例化为对象后,类中的非静态代码块、构造器、非静态属性、非静态方法被加载
② 实例化后首先执行父类的非静态代码块,父类的空参构造器
③ 再执行子类(本类)的非静态代码块,子类(本类)的构造器 (根据调用情况决定是空参还是实参) -
测试代码
class Father{ static String name = "父类静态属性"; public int age = 10; static { System.out.println("父类静态代码块"); } { System.out.println("父类非静态代码块"); } public Father(){ System.out.println("父类空参构造器"); } public Father(int age){ System.out.println("父类带参构造器"); } } class Son extends Father{ char sex = 'M'; static { System.out.println("子类静态代码块"); } { System.out.println("子类非静态代码块"); } public Son(){ System.out.println("子类空参构造器"); } public Son(char sex){ System.out.println("子类带参构造器"); } public static void main(String[] args) { System.out.println("main方法首行代码"); // 第1次实例化对象 Son s1 = new Son('m'); System.out.println("首次实例化本类对象后的第一条代码"); // 第2次实例化本类对象 Son s2 = new Son(); System.out.println("第二次实例化本类对象后的第一条代码"); // 实例化父类对象 Father f = new Father(); System.out.println("实例化父类后的第一条代码"); } }
-
执行顺序