本文共 2575 字,大约阅读时间需要 8 分钟。
java中子类与父类的初始化顺序每次遇到都会想一想,尤其是遇到复杂的子类与父类中多态和方法重载交织在一起的时候,但是总结一下,还是那个特定的规律。
看个例子吧。
class Egg{ static{ System.out.println("父类静态代码块初始化"); } private int a = 1; { System.out.println("父类代码块初始化" + a + " b=1证明成员变量已经初始化了"); } public Egg(){ System.out.println("父类构造函数初始化"); }}class BigEgg extends Egg{ static{ System.out.println("子类静态代码块初始化"); } private int b = 2; { System.out.println("子类代码块初始化 " + b + " b=2证明成员变量已经初始化了"); } public BigEgg(){ System.out.println("子类构造函数初始化"); }}public class TestClassInitSeq{ public static void main(String[] args){ new BigEgg(); }}输出结果:
父类静态代码块初始化 子类静态代码块初始化 父类代码块初始化1 b=1证明成员变量已经初始化了 父类构造函数初始化 子类代码块初始化 2 b=2证明成员变量已经初始化了 子类构造函数初始化
从输出结果可以看出这样的初始化顺序:① 如果类中存在继承关系,则首先会初始化基类(Egg),然后再是子类(BigEgg);
② 在基类中首先会初始化静态的东西,静态代码块和静态变量(类变量),谁在前就先初始化谁,静态的东西是跟着类的加载而加载的;
③ 然后是初始化子类静态的东西,静态代码块和静态变量,跟父类中的顺序相同,还是谁在前先初始化谁;
④ 接着是父类代码块和成员变量,同样也是谁在前谁先初始化;
⑤ 初始化父类的构造函数(调用有参就初始化有参构造器);
⑥ 接着初始化子类的代码块和成员变量,谁在前谁先初始化;
⑦ 初始化子类的构造函数(调用有参就初始化有参构造器)。
举个例子再来说明和验证一下:
class Father0{ private static String str = "静态变量初始化"; static{ System.out.println("父类静态代码块初始化" ); System.out.println(str); } { System.out.println("父类代码块初始化" ); } private static String s= print(); public static String print() { System.out.println("父类静态方法" ); return "父类静态成员变量的初始化" ; } public Father0() { System.out.println("父类无参构造函数初始化完成" ); show(); } public void show() { System.out.println("父类show()方法" ); }}class Son extends Father0{ static{ System.out.println("子类静态代码块初始化" ); } { System.out.println("子类代码块初始化" ); } private int i =1; private String s="子类私有成员变量" ; public Son() { System.out.println("子类构造函数初始化完成" ); System.out.println("子类成员变量初始化完成:s=" +s); show(); } public void show() { System.out.println("子类show()方法:i=" +i); }}public class TestClassLoadSeq { public static void main(String[] args){ new Son(); }}
输出结果:
父类静态代码块初始化 静态变量初始化 父类静态方法 子类静态代码块初始化 父类代码块初始化 父类无参构造函数初始化完成 子类show()方法:i=0 子类代码块初始化 子类构造函数初始化完成 子类成员变量初始化完成:s=子类私有成员变量 子类show()方法:i=1
从输出结果看,顺序完全是按照上面总结的那个顺序。不同的是父类中有了两个静态变量,而且父类中第二个静态变量指向一个静态方法,所以才有了父类静态方法的初始化。
父类构造函数中调用了一个show()方法,由于是new 子类的实例,所以执行的是子类的show()方法,但是子类的成员变量在父类构造函数执行时还没有初始化,所以此时i=0,当子类中构造函数执行时,调用show()方法,此时成员变量已经初始化了输出i=1。
实际上,本文讨论的都是真正执行的顺序,没有站在JVM的类加载的立场,JVM加载类时做了很多初始化动作,会对每个基本数据类型初始化为各个基本数据类型的0,比如int型会初始化为0,boolean型初始化为false,组合引用类型初始化为null等等。
反正,这些基础知识对后面学习还是有一定帮助的,不会让你每次遇到时都要犹豫和徘徊一下。
如有错误望指正。
转载地址:http://tuwpi.baihongyu.com/