源码
建议先给出自己的答案,不要复制然后去运行,这样就没有意义。出现错误也没有关系。
public class Main {private static int k = 1;private static Main m1 = new Main("m1");private static Main m2 = new Main("m2");private static int i = print("i");private static int n = 99;{print("初始化块");j = 100;}public Main(String name) {System.out.println((k ++) + ":" + name + ",i=" + i + ",n=" + n);++ i;++ n;}static {print("静态块");n = 100;}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) {Main m = new Main("m");}
}
输出结果
解释
这道题还是有点难度的,答案错了也没关系。耐心看完这篇博客就什么明白了。
- 首先我们需要清除当类加载时,第一步是静态的属性进行创建,此时并不会进行赋值操作,也即
k=0,m1=null,m2=null等等
。 - 然后才是开始进行赋值操作,此时
k=1
;接下来创建实例对象m1,创建对象时是执行所有的非静态属性、代码块以及方法,最后执行构造方法。此时执行第一个静态代码块,并且此时的i和n是还没有赋值的,所以输出1:初始化块,i=0,n=0"
,然后i和n都完成++操作。 - 然后执行
private int j = print("j");
,故而输出2:j,i=1,n=1
,i和n也都完成++操作。 - 当所有的非静态属性、方法等都执行完毕,就执行自己的构造函数,故而输出
3:m1,i=2,n=2
,i和n也都完成++操作。 - 此时完成了m1对象的创建。代码继续向下执行,创建m2对象,其过程同m1对象的过程一样,先完成非静态的所有属性、代码块、方法,然后再执行构造函数。这里就不作过多赘述。
- 当m2对象也创建完成,代码继续向下执行,对i进行赋值操作,也就是执行
print("i")
,故而输出7:i,i=6,n=6
,i和n也都完成++操作。 - 接着向下执行,为n赋值为99。然后是静态代码块
static{print("静态块");n = 100;}
,这里要注意静态代码块也是赋值操作。因此输出8:静态块,i=7,n=99
。 - 然后就是执行我们的main方法,跟创建m1和m2时一样,只不过此时的n以及完成了赋值操作。
总结起来就一句话,类加载时先静态,并且按照顺序从上往下加载,先进行所有静态属性的初始化,然后才是赋值。创建对象时,只执行非静态的,然后再执行构造方法。
到这里就已经结束了。需要多理解几遍,如果觉得自己已经吃透了,就可以修改一下k和n的初始值,并且打印一下y然后验证自己的结果。