关于创建一个对象的流程以及代码块和属性位置相关

在听毕向东的面向对象时,其总结了创建对象的过程:

1、加载指定的字节码文件进内存。

2、通过new在堆内存中开辟空间,分配首地址值。

3、对对象属性进行默认初始化。

4、调用与之对应的构造函数,构造函数压栈。

5、构造函数中执行隐式的语句super()访问父类中的构造函数。

6、对属性进行显示初始化。

7、调用类中的构造代码块。

8、执行构造函数中自定义的初始化代码。

9、初始化完毕,将地址赋值给制定的引用。

其中第6、7两个步骤其实有点说道的,毕向东这种情况是正常的情况,也就是在类的一开始就对属性进行声明。

但是也有很特殊的情况例如:

package cn.haiyisoft2;

public class ClassDemo09 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 构造代码块
		children c1 =new children();
		System.out.println(c1.age);
		children c2 =new children(5);
		System.out.println(c2.age);
	}

}

class children {
	//int age=8;
	children() {
		System.out.println("children()");
	}

	children(int age) {
		System.out.println("children(int age)");
		this.age=age;
	}

	private void cry() {
		System.out.println("cry!");
	}

	{
		age=10;
		cry();
	}
	 int age=8;
}

package cn.haiyisoft2;

public class ClassDemo08 {

	/**
	 * @param args
	 */

	//static {
		//System.out.println("a");
	//}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 静态代码块练习
		//staticcode02 s02 = new staticcode02();
		System.out.println(staticcode02.age);
	}

	//static {
		//System.out.println("b");
	//}

}

class staticcode02 {
	
	static {
		age=10;
		//System.out.println("static code"+" "+"age="+age);
		//《深入理解java虚拟机》(第二版)的225页,定义在静态语句块之后的变量,在静态语句块中可以赋值,不能访问。
	}
	static int age=9;

	void show() {
		System.out.println("show fun");
	}

	static void show1() {
		System.out.println("show1 fun");
	}
}


是的,就是这样在类中不管是类变量还是实例变量,我都是把变量定义在了静态/构造代码块的后面(这样非常不好,极度不推荐),就像《深入理解java虚拟机》(第二版)的225页,定义在静态语句块之后的变量,在静态语句块中可以赋值,不能访问。其实构造代码块如果遇到了属性在构造代码块之后声明时,也会只能赋值不能访问。

而且初始化时不论是对类还是对象进行初始化,都会按照在类声明中出现的次序,执行属性以及各个初始化块(java核心技术(基础版)第八版125页,参考阅读java语言规范中文第三版 8.3.2.3).

如果让类的构造器依赖于属性声明的顺序,那么显得很奇怪并且会引起错误,所以建议将初始化块放在属性定义之后。


posted @ 2016-06-25 01:33  明月镇魂  阅读(224)  评论(0编辑  收藏  举报