本帖最后由 田旭阳 于 2012-9-5 22:39 编辑
1.class Parent{
2. static String name = "hello";
3. static {
4. System.out.println("parent static block");
5. }
6. {
7. System.out.println("parent block");
8. }
9. public Parent(){
10. System.out.println("parent constructor");
11. }
12.}
13.
14.class Child extends Parent{
15. static String childName = "hello";
16. static {
17. System.out.println("child static block");
18. }
19. {
20. System.out.println("child block");
21. }
22. public Child(){
23. System.out.println("child constructor");
24. }
25.}
26.
27.public class StaticIniBlockOrderTest {
28.
29. public static void main(String[] args) {
30. new Child();//语句(*)
31. }
32.}
当执行完语句(*)时,打印结果是这样一个顺序:parent static block,child static block,parent block,parent constructor,child block,child constructor。
分析:当执行new Child()时,它首先去看父类里面有没有静态代码块,如果有,它先去执行父类里面静态代码块里面的内容,当父类的静态代码块里面的内容执行完毕之后,接着去执行子类(自己这个类)里面的静态代码块,当子类的静态代码块执行完毕之后,它接着又去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法,这个就是一个对象的初始化顺序。
总结:对象的初始化顺序:首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法。总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。
父类Static->子类static->父类缺省{}->父类构造函数->子类缺省{}->子类构造函数
(静态变量、静态初始化块)>(变量、初始化块)>构造器
注意:子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。
// 1、因为new用到了Zi.class,并且子类继承了父类。所以会先找到Fu.class,再找到Zi.class文件并加载到内存中
// 2、执行 父类静态代码块
// 3、执行子类静态代码块
//a父类构造代码块
//b父类构造函数
// 4、在堆内存中开辟空间,分配内存地址
// 5、在堆内存中建立对象的特有属性,并进行默认初始化
// 6、对属性显式初始化
// 7、子类构造代码块
// 8、子类构造函数
// 9、将内存地址付给栈内存中的z变量
|