关于类方法块的调用顺序,一直没有进行总结记录过,中午趁着午饭时间,稍微温习下最基础的内容,并记录下。
静态代码块、普通代码块、构造函数块:
1 public class Test { 2 3 public static void main(String[] args) { 4 5 new Square(); 6 System.out.println("--------Next---------"); 7 new Circle(); 8 9 } 10 } 11 class Shape { 12 13 public Shape() { 14 System.out.println("Shape Constructor."); 15 } 16 17 static { 18 System.out.println("Shape static code."); 19 } 20 21 { 22 System.out.println("Shape normal code."); 23 } 24 25 } 26 class Square extends Shape{ 27 28 public Square() { 29 System.out.println("Square Constructor."); 30 } 31 32 static { 33 System.out.println("Square static code."); 34 } 35 36 { 37 System.out.println("Square normal code."); 38 } 39 40 } 41 class Circle extends Shape { 42 43 public Circle() { 44 System.out.println("Circle Constructor."); 45 } 46 47 static { 48 System.out.println("Circle static code."); 49 } 50 51 { 52 System.out.println("Circle normal code."); 53 } 54 55 }
从输出结果发现, 在创建一个对象的时候, 会发生如下的过程:
父类未被加载过:
- 父类是否被加载过, 没有加载则进行加载, 父类静态代码块随之调用
- 加载子类, 子类静态代码块随之调用
- 调用父类的普通代码块
- 调用父类的构造方法
- 调用子类的普通代码块
- 调用子类的构造方法
-----------------Next------------------------
父类已经被加载过:
- 加载子类, 子类静态代码块随之调用
- 调用父类的普通代码块
- 调用父类的构造方法
- 调用子类的普通代码块
- 调用子类的构造方法
注意:
在子类的构造方法中, super()必须先被调用, 若没有写, 运行时会自动调用super()方法;
如果父类没有无参构造方法, 需要手动进行super()的调用。
总结:
在子类构造方法中, 不管是手动调用父类构造方法还是运行时自动调用, 必须满足:
1. 子类的构造方法必须先调用父类中的某个构造方法;
2. 被子类调用的父类构造方法在父类中必须是存在的.
通过反编译class文件, 会发现其实普通代码块的代码被合并到构造方法中了,在构造方法的内的最上部,所以出现上面普通代码块在构造方法前执行的结果。
另外编码时需要注意一点:因为静态变量和静态代码块的执行顺序是根据代码编写的顺序进行执行的,所以静态变量要定义在静态代码块的前面。