面试中我们常常会问到关于类初始化的问题,那么关于一个类的初始化到底是按照怎么的顺序进行的呢
假如一个Son 类继承了 Parent 类 当我们实例化Son的时候是先执行父类还是先执行子类呢?
可能有的开发会说当然是先执行父类了 没错 就是先从父类开始执行的
那么当我们执行父类的时候 当父类和子类都有 静态成员变量 有普通的成员变量时 静态代码块 构造器 时
他们之间的执行顺序到底是怎么样的呢?
废话不多说请看代码
public class DeBugPrint {
public DeBugPrint(String msg) {
System.out.println(msg);
}
}
public class Parent {
DeBugPrint deBugPrint1 = new DeBugPrint("Parent的普通成员变量初始化了");
static DeBugPrint deBugPrint2 = new DeBugPrint("Parent的静态成员变量初始化了");
Parent(){
deBugPrint2 = new DeBugPrint("执行了构造方法 对 Parent的静态成员变量进行赋值");
deBugPrint1 = new DeBugPrint("执行了构造方法 对 Parent的普通成员变量进行赋值");
}
static {
deBugPrint2 = new DeBugPrint("执行了静态代码块 对 Parent的静态成员变量进行赋值");
}
}
public class Son extends Parent{
DeBugPrint deBugPrint1 = new DeBugPrint("Son的普通成员变量初始化了");
static DeBugPrint deBugPrint2 = new DeBugPrint("Son的静态成员变量初始化了");
Son(){
deBugPrint2 = new DeBugPrint("执行了构造方法 对 Son的静态成员变量进行赋值");
deBugPrint1 = new DeBugPrint("执行了构造方法 对 Son的普通成员变量进行赋值");
}
static {
deBugPrint2 = new DeBugPrint("执行了静态代码块 对 Son的静态成员变量进行赋值");
}
public static void funStatic() {
System.out.println("执行了static修饰的funStatic方法");
}
}
public class test1 {
public static void main(String[] args) {
Son.funStatic();
}
}
test1的执行结果如下:
Parent的静态成员变量初始化了
执行了静态代码块 对 Parent的静态成员变量进行赋值
Son的静态成员变量初始化了
执行了静态代码块 对 Son的静态成员变量进行赋值
执行了static修饰的funStatic方法
从这个结果中我们可以看出 当直接调用静态方法时 只对父类及其子类的静态资源(静态变量及静态代码块)进行初始化
public class test2 {
public static void main(String[] args) {
Son son = new Son();
}
}
test2的执行结果如下:
Parent的静态成员变量初始化了
执行了静态代码块 对 Parent的静态成员变量进行赋值
Son的静态成员变量初始化了
执行了静态代码块 对 Son的静态成员变量进行赋值
Parent的普通成员变量初始化了
执行了构造方法 对 Parent的静态成员变量进行赋值
执行了构造方法 对 Parent的普通成员变量进行赋值
Son的普通成员变量初始化了
执行了构造方法 对 Son的静态成员变量进行赋值
执行了构造方法 对 Son的普通成员变量进行赋值
当我们对Son进行实例化时,这其实也是一个类完整的初始化过程,也是我们主题要研究的内容对于继承关系,对于静态变量,对于静态代码块他们之间的实例化顺序,看到这个结果我们可能会带着些许的疑惑,不过仔细研究也会发现这样其实也是合情合理
public class test3 {
public static void main(String[] args) {
Son.funStatic();
System.out.println("+++++++++++++++++++++++++++++++++++++++++++");
Son son1 = new Son();
}
}
test3的执行结果如下:
Parent的静态成员变量初始化了
执行了静态代码块 对 Parent的静态成员变量进行赋值
Son的静态成员变量初始化了
执行了静态代码块 对 Son的静态成员变量进行赋值
执行了static修饰的funStatic方法
+++++++++++++++++++++++++++++++++++++++++++
Parent的普通成员变量初始化了
执行了构造方法 对 Parent的静态成员变量进行赋值
执行了构造方法 对 Parent的普通成员变量进行赋值
Son的普通成员变量初始化了
执行了构造方法 对 Son的静态成员变量进行赋值
执行了构造方法 对 Son的普通成员变量进行赋值
这个结果你有没有感到意外呢,静态资源只被调用funStatic()静态方法时被初始化了一次,当对Son进行实例化时则静态资源没有被重新初始化,这也跟static关键字的特性有关,有兴趣的同学可以深入研究.
总结:
有父类 优先初始化父类
有static修饰 优先执行所有static
先初始化普通成员变量 再 执行构造器
第一次写博客,肯定有不足的地方,若有错误之处请及时指出以免误导他人.如果问题可在评论去提出共同探讨相互学习.