看过Thinking in java的人都知道,在不考虑父类的情况下,类的初始化顺序相对简单,总体是先静态的,然后是非静态的。这里都包括成员变量和代码块。对于静态变量和静态代码块,不管它们在何处定义,总是按照其先后顺序进行初始化。同理,非静态变量和非静态代码块也是如此。
下面上热菜:

public class Test1 {
	public static int k = 0;
	public static Test1 initOrder1 = new Test1("t1");
	public static Test1 initOrder2 = new Test1("t2");
    public static final int m = -1;
	public static int i = print("i");
	public static int n = 99;
	public int j = print("j");

	{
		print("构造块");
	}

	static {
		print("静态块");
	}

	public Test1(String str) {
		System.out.println((++k) + ":" + str + " i=" + i + " n=" + n + " m=" + m);
		++i;
		++n;
	}

	public static int print(String str) {
		System.out.println((++k) + ":" + str + " i=" + i + " n=" + n + " m=" + m);
		++n;
		return ++i;
	}

	public static void main(String[] args) {
		Test1 initOrder =  new Test1("init");
	}

}




什么!!!居然还有这样的的:


public static Test1 initOrder1 = new Test1("t1");



对我这种小白来说,这太不能理解了。伤脑细胞!


我们先看看答案吧:


1:j i=0 n=0 m=-1
2:构造块 i=1 n=1 m=-1
3:t1 i=2 n=2 m=-1
4:j i=3 n=3 m=-1
5:构造块 i=4 n=4 m=-1
6:t2 i=5 n=5 m=-1
7:i i=6 n=6 m=-1
8:静态块 i=7 n=99 m=-1
9:j i=8 n=100 m=-1
10:构造块 i=9 n=101 m=-1
11:init i=10 n=102 m=-1




按照惯例,程序进入main()方法后,在调用new Test1()的一瞬间,Test1开始初始化了,k=0。当进行到public static Test1 initOrder1 = new Test1("t1");的时候,就要开始实例化了,所以接下来的静态变量都先等着,等排在前面的initOrder1先办完事了,才有你们这群小屁孩的事。因为静态变量属于类,而非类的实例,所以我initOrder1只好先对实例变量和非静态代码块下手了(小鲜肉,我来了。。。)。所以就会执行如下语句:


public int j = print("j");

	{
		print("构造块");
	}



得到输出:


1:j i=0 n=0 m=-1
2:构造块 i=1 n=1 m=-11




然后再调用构造器,就可以完成对initOrder1的初始化,顺便打印出了


3:t1 i=2 n=2 m=-1



接下来该初始化initOrder2了,原理同上。打印出:


4:j i=3 n=3 m=-1
5:构造块 i=4 n=4 m=-1
6:t2 i=5 n=5 m=-1



然后继续其他成员的初始化。注意,当初始化到了


public static int n = 99;



就会初始化静态代码块哟,要注意哈。别以为是顺序下来的。当初始化全部完成后,然后调用Test1("init"),至此,完成了mian()方法中的变量初始化。大功告成。



在虚拟机进行类加载的过程中,有一个准备阶段。准备阶段是正式为类变量分配内存并设置初始值的阶段,而且变量所使用的内存都将在方法区中进行分配。强调一下,此时金分配内存的是类变量(即被static修饰的变量),不包括实例变量,实例变量会和对象实例化的时候随着对象一起分配到java堆中。而且,在准备阶段过后,类变量如k和n的值为0, 而非通过=符号来赋值0和99。但是对于final static的变量m来说,情况就有点不一样。m在准备阶段就会被赋予初值-1,并放入常量池中。



如果有什么说错或者不清楚的地方,欢迎各位看官不吝批评指正。