本文是看了网友的一篇文章后整理所得,该文章链接已在本文底部贴出,在这里非常感谢这位网友的分享!
我们先来看段代码
public class InitTest{
public static int k = 1;
//public static InitTest t1 = new InitTest("t1");
//public static InitTest t2 = new InitTest("t2");
public static int i = print("i");
public static int n = 99;
public int j = print("j");
{
print("Creat");
}
static {
print("Static");
}
public InitTest(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++n; ++ i;
}
public static int print(String str){
System.out.println((++k) +":" + str + " i=" + i + " n=" + n);
++n;
return ++ i;
}
public static void main(String[] args){
System.out.println("=========start============");
InitTest t = new InitTest("init");
System.out.println("=========end============");
}
}
相信大多数同行在不运行本段代码的情况都能说出程序执行的结果
2:i i=0 n=0
3:Static i=1 n=99
=========start============
4:j i=2 n=100
5:Creat i=3 n=101
6:init i=4 n=102
=========end============
这里先补充些基础知识
类在加载时会先给类变量分配存储空间并给该变量设置系统默认的默认值,然后按源码顺序执行这些类变量的赋值语句及静态代码块
当实例化一个有继承关系的子类时,其执行顺序如下
1、执行父类的类变量赋值语句和静态代码块 (此时的类变量赋值语句和静态代码块的执行先后顺序取决于它们在源代码中的顺序)
2、执行字类的类变量赋值语句和静态代码块类变量赋值语句和静态代码块在其所属类第一次加载时执行且仅执行一次
下面的过程发生在类实例化时
3、执行父类的实例变量赋值语句、非静态代码块和构造函数
4、执行子类的实例变量赋值语句、非静态代码块和构造函数
如果此时将上面代码中屏蔽的两句代码放开,结果又是如何呢?
先看看运行的结果:
2:j i=0 n=0
3:Creat i=1 n=1
4:t1 i=2 n=2
5:j i=3 n=3
6:Creat i=4 n=4
7:t2 i=5 n=5
8:i i=6 n=6
9:Static i=7 n=99
=========start============
10:j i=8 n=100
11:Creat i=9 n=101
12:init i=10 n=102
=========end============
通过打断点分析代码的执行步骤发现执行顺序如下:
1、代码执行了类变量k=1的赋值操作
2、执行类变量t1时由于类变量已经初始化一次了,故直接按类实例化的流程执行
3、执行类变量t2时同上
4、执行类变量i、n的赋值语句
5、执行静态代码块中的语句
6、执行main方法中的实例化语句,执行实例变量的赋值语句、非静态代码块、构造函数