本文主要探究Java类加载和初始化执行顺序
父类
public class Father {
// 普通类变量
private int i = test1();
// 静态类变量
private static int j = test2();
// 普通代码块
{
System.out.println("父类普通代码块执行");
}
// 静态代码块
static {
System.out.println("父类静态代码块执行");
}
// 构造方法
public Father() {
System.out.println("父类构造方法执行");
}
private int test1() {
System.out.println("[test1]父类普通类变量初始化");
return 1;
}
private static int test2() {
System.out.println("[test2]父类静态类变量初始化");
return 2;
}
}
子类
public class Child extends Father{
// 普通类变量
private int i = test1();
// 静态类变量
private static int j = test2();
// 普通代码块
{
System.out.println("子类普通代码块执行");
}
// 静态代码块
static {
System.out.println("子类静态代码块执行");
}
// 构造方法
public Child() {
System.out.println("子类构造方法执行");
}
private int test1() {
System.out.println("[test1]子类普通类变量初始化");
return 1;
}
private static int test2() {
System.out.println("[test2]子类静态类变量初始化");
return 2;
}
public static void main(String[] args) {
System.out.println("===============初始化==============");
new Child();
}
}
运行结果:
[test2]父类静态类变量初始化
父类静态代码块执行
[test2]子类静态类变量初始化
子类静态代码块执行
===============初始化==============
[test1]父类普通类变量初始化
父类普通代码块执行
父类构造方法执行
[test1]子类普通类变量初始化
子类普通代码块执行
子类构造方法执行
结果分析:
从运行结果可看出在初始化之前要先执行类加载。子类加载时会先加载父类。类加载就是执行字节码文件中的clinit()方法,clinit()方法由类静态变量赋值代码和类静态代码块组成,执行顺序:
- 类静态变量赋值
- 类静态代码块
以下两种情况下会发生类加载:
- 类初始化
- 类的main方法执行
子类初始化时,也会先初始化父类,初始化顺序:
- 父类普通类变量赋值
- 父类普通代码块执行
- 父类构造方法执行
- 子类普通类变量赋值
- 子类普通代码块执行
- 子类构造方法执行