在听毕向东的面向对象时,其总结了创建对象的过程:
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).
如果让类的构造器依赖于属性声明的顺序,那么显得很奇怪并且会引起错误,所以建议将初始化块放在属性定义之后。
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/17699.html