Java类加载和实例化的执行顺序详解
类加载:当程序主动使用某个类时,如果该类还未被加载到内存中,系统会通过加载,链接,初始化三个步骤来对类进行初始化,JVM连续完成三个步骤,统称为类加载或类初始化。 加载类的时机:第一次需要使用类信息时加载。 类加载的原则:延迟加载,能不加载就不加载。 触发类加载的几种情况: (1)调用静态成员时,会加载静态成员真正所在的类及其父类。通过子类调用父类的静态成员时,只会加载父类而不会加载子类 (2)第一次 new 对象的时候加载,以后不需再次加载 (3)加载子类会先加载父类。
加载方法并不等于执行方法,初始化变量则会赋值。 类加载的顺序应为:加载静态方法—>初始化静态变量—>执行静态代码块 实例化时,先加载非静态方法—>实例化非静态变量—>执行构造代码块—>执行构造函数
public class InitializeDemo { //第一个加载的 private static int k = 1; //第二个加载的 /** * new 了一个实例,所以开始实例化 * 1.加载非静态方法:{ print("构造块"); j=100; } * 2.实例化非静态方法: private int j = print("j"); * 3.执行构造代码块::构造块 i= n= * 4.执行构造函数:private static InitializeDemo t1= new InitializeDemo("t1"); */ private static InitializeDemo t1= new InitializeDemo("t1"); //第三个加载,具体实现同上 private static InitializeDemo t2= new InitializeDemo("t2"); //第四个加载 打印:i i= 6 n = 6 private static int i = print("i"); //第五个加载 加载静态代码块 static { print("静态块"); n = 100; } //第六个加载 private static int n = 99; //第七个加载 { print("构造块"); j=100; } public InitializeDemo(String str) { System.out.println((k++) + ":" + str + " i= " + i + " n = " + n); ++i; ++n; } //第八个加载:此变量在类加载的时候并不初始化,在实例化类的时候初始化(构造块,实例化的时候执行) private int j = print("j"); public static int print(String str) { System.out.println((k++) + ":" + str + " i= " + i + " n = " + n); ++n; return ++i; } public static void main(String[] args) { InitializeDemo n = new InitializeDemo("初始化"); } }
结果如下所示:
1:构造块 i= 0 n = 0 2:j i= 1 n = 1 3:t1 i= 2 n = 2 4:构造块 i= 3 n = 3 5:j i= 4 n = 4 6:t2 i= 5 n = 5 7:i i= 6 n = 6 8:静态块 i= 7 n = 7 9:构造块 i= 8 n = 99 10:j i= 9 n = 100 11:初始化 i= 10 n = 101