一个对象的实例化过程:Person p=new Person();
1.jvm会读取指定的路径下的Person.class文件,并加载进内存。
并会先加载Person中的父类(如果有父类对象的情况下)。
2.在堆内存中开辟空间,分配地址
3.并在对象空间中,对对象中的属性进行默认初始化。
4.调用对应的构造函数进行初始化。
5.在构造函数中,第一行会先调用父类中的构造函数进行初始化。
6.父类初始化完毕后,再对子类的属性进行显式初始化。
7.再进行子类构造函数的特定初始化。
8.初始化完毕后,将地址值赋值给引用变量
通过super初始化父类内容时,子类的成员变量并未显式初始化。等super()父类初始化完毕后,才进行子类的成员变量初始化
输出为zi run0
zi run8
初始化顺序:默认初始化——>显式初始化—— >构造函数初始化(没父类)看起来
实际构造器是先加载的,先会进行父类的的初始化
在super对父类进行初始化完毕后,才会进行子类的成员变量显式初始化。
Q: 1.子父类静态变量的加载顺序?
1.jvm会读取指定的路径下的Person.class文件,并加载进内存。
并会先加载Person中的父类(如果有父类对象的情况下)。
2.在堆内存中开辟空间,分配地址
3.并在对象空间中,对对象中的属性进行默认初始化。
4.调用对应的构造函数进行初始化。
5.在构造函数中,第一行会先调用父类中的构造函数进行初始化。
6.父类初始化完毕后,再对子类的属性进行显式初始化。
7.再进行子类构造函数的特定初始化。
8.初始化完毕后,将地址值赋值给引用变量
通过super初始化父类内容时,子类的成员变量并未显式初始化。等super()父类初始化完毕后,才进行子类的成员变量初始化
object类是在虚拟机运行时直接加载的。
class Fu
{
Fu()
{
super();
show();
return;
}
void show()
{
System.out.println("fu run");
}
}
class Zi extends Fu
{
Zi()
{
super();
return;
}
int num=8;
void show()
{
System.out.println("zi run"+num);
}
}
输出为zi run0
zi run8
图解:
1.main函数进栈并加载引用变量z
2.此时,由于引用了Zi类,Zi类准备进方法区,但发现extends关键字,Fu类进方法区。
3.父类加载完,子类进方法区,子类中super指向父类。此时需要进行对象的建立,在堆中会创建一个new Zi对象,同时分配一个内存地址0x0067。并对num进行默认初始化。
4.子类构造函数进栈,this持有堆中的地址值,由于super是第一条语句所以父类构造函数立刻进栈,也有this也指向堆中的地址值,所以Fu类构造函数的show方法会执行Zi类中的show方法。此时由于显式初始化并未进行,所以num值为0.
6.Fu类的构造函数弹栈,进行默认初始化,Zi类构造函数加载,弹栈。将地址值赋给引用变量
初始化顺序:默认初始化——>显式初始化—— >构造函数初始化(没父类)看起来
实际构造器是先加载的,先会进行父类的的初始化
在super对父类进行初始化完毕后,才会进行子类的成员变量显式初始化。
Q: 1.子父类静态变量的加载顺序?
2.构造代码块和显式初始化的顺序?ps:已知:静态代码块>构造代码块>构造函数(应该是显式初始化先进行)
http://blog.csdn.net/kingzone_2008/article/details/45015301
http://bbs.csdn.net/topics/390635323?page=1(ifvlr的回答)
在编译时的编译器看来会默认将构造代码块中的代码移动到构造方法中,并且移动到构造方法内容的前面。