`

Java对象初始化顺序

 
阅读更多

前几天与fwb同学说起java笔试题,想起这个东西经常被考,重温了下think in java,总结如下:
1. 使用new新建对象时,初始化顺序为:静态变量>成员变量>构造方法。 静态初始化块以静态变量对待
2. 建立类的Class对象,但没有执行new时(如访问任何静态变量、或者调用静态方法、或者调用Class.forName方法等。使用 Class<A> a = A.class则不会触发)都会进行静态变量的初始化。此时成员变量、构造方法未初始化。静态变量只会被初始化一次。
3. 同种变量的初始化,按照代码中的书写顺序进行,无论变量声明在类头、方法之间、类尾。
4. 执行构造方法时,从祖先至子孙依次进行。“创建过程是由基类'向外'扩散的”。那么如果new一个子类对象,子类构造方法中的代码应在父类静态变量>父类成员变量>父类构造方法>子类静态变量>子类成员变量之后执行。

另附think in java 中对于对象创建过程的描述。有助于深入了解:(摘自think in java第三版,机工,第四章)

假设有个名为Dog的类:

1. 当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。

2. 然后载入Dog.class(这将创建一个Class对象), 有关静态初始化的动作都会执行。因此,静态初始化只在Class对象首次加载的时候执行一次。

3. 当你用new Dog()创建对象的时候,首先在堆上为Dog对象分配足够高的存储空间。

4. 这块存储空间会被清零,这就自动的将Dog中的所有基本类型数据设置成了默认值(对于数字来说就是0,对布尔型和字符型也相同),而引用则被设置成了null。

5. 执行所有出现于域定义处的初始化动作。

6. 执行构造器。

举例如下:

public class Test_a extends Test_b {
	static Test_f f = new Test_f();
	Test_e e = new Test_e();

	Test_a() {
		System.out.println("子类构造器");
	}

	public static void main(String args[]){
		new Test_a();
	}
}

class Test_b {
	static Test_d d = new Test_d();
	Test_c c = new Test_c();

	Test_b() {
		System.out.println("父类构造器");
	}
}

class Test_c {
	Test_c() {
		System.out.println("父类非静态成员变量");
	}
}

class Test_d {
	Test_d() {
		System.out.println("父类静态成员变量");
	}
}

class Test_e {
	Test_e() {
		System.out.println("子类非静态成员变量");
	}
}

class Test_f {
	Test_f() {
		System.out.println("子类静态成员变量");
	}
}

执行后结果如下:

父类静态成员变量(仅在类加载到内存时初始化一次,也只存在一份)
子类静态成员变量(仅在类加载到内存时初始化一次,也只存在一份)
父类非静态成员变量(每创建一次对象就会被初始化一次,创建一次)
父类构造器
子类非静态成员变量(每创建一次对象就会被初始化一次,创建一次)
子类构造器
分享到:
评论
1 楼 xuanmingwu 2012-03-09  

相关推荐

Global site tag (gtag.js) - Google Analytics