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
