1.前言
java的类中有静态代码块,动态代码块,构造方法,那么你知道他们的执行顺序吗?如果你不懂,那么真该好好了解一下了,阿里笔试中就有类似的问题。
2.代码分析
我们分别创建一个Father类与Son类:
//Father.java
public class Father {
static{
System.out.println("父类静态代码块执行...");
}
{
System.out.println("父类动态代码块执行");
}
public Father(){
System.out.println("父类构造方法执行");
}
}
//Son.java
public class Son extends Father{
static{
System.out.println("子类静态代码块执行...");
}
{
System.out.println("子类动态代码块执行");
}
public Son(){
System.out.println("子类构造方法执行");
}
}
下面实例化子类后的运行结果
父类静态代码块执行…
子类静态代码块执行…
父类动态代码块执行
父类构造方法执行
子类动态代码块执行
子类构造方法执行
我们可以很清楚的看到执行顺序
3.原理剖析
首先明确一个概念,静态代码块随着类的class文件被加载进jvm内存而执行。另外,一个类的class文件只会被读入jvm内存一次。
那么什么情况下算是类第一次被使用呢?
-
第一次实例化该类的对象
-
第一次调用该类的静态成员
-
第一次实例化该类的派生类的对象
3.1.静态代码块
java中,实例化子类对象时,jvm会先加载父类的class文件,然后再加载子类的class文件。所以程序运行时,会先执行父类的静态代码块,再执行子类的静态代码块
当我们创建第二个Son对象,查看输出结果
Son son = new Son();
System.out.println("------------------华丽的分割线--------------");
Son son2 = new Son();
父类静态代码块执行…
子类静态代码块执行…
父类动态代码块执行
父类构造方法执行
子类动态代码块执行
子类构造方法执行
------------------华丽的分割线--------------
父类动态代码块执行
父类构造方法执行
子类动态代码块执行
子类构造方法执行
可以看到只有第一个实例化对象执行了静态代码块。
3.2.动态代码块(普通代码块)
java中,动态代码块是在实例化对象时便会被执行,他优先于构造方法执行。其可以用来为成员属性赋值。
3.3.构造方法
构造方法随着对象的创建而执行,父类的构造方法会在派生类的方法中被调用。即使我们在子类构造方法中没有调用父类的构造方法,jvm默认会调用父类的无参构造方法1。而且逐层向上调用,使每个父类的构造方法都被调用到。
4.总结
通过分析,我们可以知道执行顺序依次为:
父类静态代码块->子类静态代码块->父类动态代码块->父类构造方法->子类动态代码块->子类构造方法
如果父类存在有参构造方法,没有无参构造方法,则会编译错误 ↩︎