阿里的变态题,关于java对象初始化顺序,颠覆了。
public class TestConstructOrder {
	public static int k = 0;
	public static int k1;
	public int k2;
	public static TestConstructOrder t1 = new TestConstructOrder("t1");
	public static TestConstructOrder t2 = new TestConstructOrder("t2");
	public static int i = print("i");
	public static int n = 99;
	public int j = print("j");
	{
		print("构造块");
	}
	static {
		print("静态块");
	}
	public TestConstructOrder(String str) {
		System.out.println((++k) + ":" + str + "	i=" + i + "	n=" + n);
		++i;
		++n;
	}
	public static int print(String str) {
		System.out.println((++k) + ":" + str + "	i=" + i + "	n=" + n);
		++n;
		return ++i;
	}
	/**
	 * 
	 */
	public static void main(String[] args) {
		TestConstructOrder t = new TestConstructOrder("init");
	}
}
结果是:
1:j	i=0	n=0
2:构造块	i=1	n=1
3:t1	i=2	n=2
4:j	i=3	n=3
5:构造块	i=4	n=4
6:t2	i=5	n=5
7:i	i=6	n=6
8:静态块	i=7	n=99
9:j	i=8	n=100
10:构造块	i=9	n=101
11:init	i=10	n=102
ttt:0,0
有人能够说清楚具体的过程么?我是说不清楚了...
              
------解决方案--------------------初始化(initialization)其实包含两部分:
1.类的初始化(initialization class & interface)
2.对象的创建(creation of new class instances)。
因为类的初始化其实是类加载(loading of classes)的最后一步,所以很多书中把它归结为“对象的创建”的第一步。其实只是看问题的角度不同而已。为了更清楚的理解,这里还是分开来。
顺序:
应为类的加载肯定是第一步的,所以类的初始化在前。大体的初始化顺序是:
类初始化 -> 子类构造函数 -> 父类构造函数 -> 实例化成员变量 -> 继续执行子类构造函数的语句
下面结合例子,具体解释一下。
1。类的初始化(Initialization classes and interfaces),其实很简单,具体来说有:
(a)初始化类(initialization of class),是指初始化static field 和执行static初始化块。
例如:
class Super {
        static String s = “initialization static field”; //初始化static field,其中“= “initialization static field” ”又叫做static field initializer
        // static初始化块,又叫做static initializer,或 static initialization block
        static {
        System.out.println(“This is static initializer”);
}
}
btw,有些书上提到static initializer 和 static field initializer 的概念,与之对应的还有 instance initializer 和 instance variable initializer。例子中的注释已经解释了其含义。
(b)初始化接口(initialization of interface),是指初始化定义在该interface中的field。
*注意*
--initialization classes 时,该class的superclass 将首先被初始化,但其实现的interface则不会。
--initialization classes 时,该class的superclass,以及superlcass的superclass 会首先被递归地初始化,一直到java.lang.Object为止。但initialiazation interface的时候,却不需如此,只会初始化该interface本身。
--对于由引用类变量(class field)所引发的初始化,只会初始化真正定义该field的class。
--如果一个static field是编译时常量(compile-time constant),则对它的引用不会引起定义它的类的初始化。
为了帮助理解最后两点,请试试看下面的例子:
public class Initialization {
        
        public static void main(String[] args) {
                
                System.out.println(Sub.x); // Won't cause initialization of Sub, because x is declared by S, not Sub.
                                         // 不会引起Sub类的初始化,因为x是定义在Super类中的
                System.out.println("-------------------------");
                System.out.println(Sub.y); // Won't cause initialization of Sub, because y is constant.
                                         // 不会引起Sub类的初始化,因为y是常量
                System.out.println("-------------------------");
                System.out.println(Sub.z = 2004); // Will cause initialization of Sub class