1. 概述
  1. 在Java中所有的变量在使用前都需要初始化。如果我们不初始化,则编译器会为变量初始化一个默认值(例如,int类型的变量的初始化默认值是0)。但是初始化的顺序是什么样的,很多人搞不清楚(我以前也搞不清楚),这篇文章就是为了说明初始化的顺序是什么样的。
  1. 说明
  1. 本例子用到四个类:Person、Student、Dog、Order,其中Student继承了Person。
  2. 下文所说的静态初始化包括:静态代码块初始化、静态变量初始化。
  3. 下文所说的非静态初始化包括;非静态代码块初始化、普通变量初始化。
  1. 举例
  1. Person类代码如下:
1 public class Person implements Serializable {
 2 
 3     // 构造器初始化
 4     public Person() {
 5         name = "父类构造器初始化10。。。";
 6         System.out.println(this.name);
 7     }
 8 
 9     // 代码块初始化
10     {
11         String str3 = "父类代码块初始化7。。。";
12         System.out.println(str3);
13     }
14 
15     // 静态代码块初始化
16     static {
17         String str4 = "父类静态代码块初始化1。。。";
18         System.out.println(str4);
19     }
20 
21     /**
22      * 
23      */
24     private static final long serialVersionUID = -2803279990673361523L;
25     private String name;// 姓名
26     private int age;// 年龄
27     // 定义时普通变量初始化
28     private Order order = new Order("父类定义时初始化8。。。");
29     // 定义时静态变量初始化
30     private static Dog dog = new Dog("父类定义时静态初始化2。。。");
31 
32     // 代码块初始化
33     {
34         String str1 = "父类代码块初始化9。。。";
35         System.out.println(str1);
36     }
37 
38     // 静态代码块初始化
39     static {
40         String str2 = "父类静态代码块初始化3。。。";
41         System.out.println(str2);
42     }
43 
44     public Person(String name, int age) {
45         this.name = name;
46         this.age = age;
47     }
48 
49     public String getName() {
50         return name;
51     }
52 
53     public void setName(String name) {
54         this.name = name;
55     }
56 
57     public int getAge() {
58         return age;
59     }
60 
61     public void setAge(int age) {
62         this.age = age;
63     }
64 
65     public static Dog getDog() {
66         return dog;
67     }
68 
69     public static void setDog(Dog dog) {
70         Person.dog = dog;
71     }
72 
73     public Order getOrder() {
74         return order;
75     }
76 
77     public void setOrder(Order order) {
78         this.order = order;
79     }
80 }
  1. View Code
  2. Student类代码如下:
1 public class Student extends Person implements Serializable {
 2 
 3     // 代码块初始化
 4     {
 5         String str1 = "子类代码块初始化11。。。";
 6         System.out.println(str1);
 7     }
 8 
 9     // 静态代码块初始化
10     static {
11         String str2 = "子类静态代码块初始化4。。。";
12         System.out.println(str2);
13     }
14 
15     /**
16      * 
17      */
18     private static final long serialVersionUID = -6642330930111509531L;
19     private float score;// 分数
20     private String grade;// 班级
21     // 定义时普通变量初始化
22     private Order order = new Order("子类定义时初始化12。。。");
23     // 定义时静态变量初始化
24     private static Dog dog = new Dog("子类定义时静态初始化5。。。");
25 
26     // 代码块初始化
27     {
28         String str1 = "子类代码块初始化13。。。";
29         System.out.println(str1);
30     }
31 
32     // 静态代码块初始化
33     static {
34         String str2 = "子类静态代码块初始化6。。。";
35         System.out.println(str2);
36     }
37 
38     // 构造器初始化
39     public Student() {
40         grade = "子类构造器初始化14。。。";
41         System.out.println(this.grade);
42     }
43 
44     public float getScore() {
45         return score;
46     }
47 
48     public void setScore(float score) {
49         this.score = score;
50     }
51 
52     public String getGrade() {
53         return grade;
54     }
55 
56     public void setGrade(String grade) {
57         this.grade = grade;
58     }
59 
60     public Order getOrder() {
61         return order;
62     }
63 
64     public void setOrder(Order order) {
65         this.order = order;
66     }
67 
68     public static Dog getDog() {
69         return dog;
70     }
71 
72     public static void setDog(Dog dog) {
73         Student.dog = dog;
74     }
75 }
  1. View Code
  2. Dog类代码如下:
1 public class Dog implements Serializable {
 2 
 3     /**
 4      * 
 5      */
 6     private static final long serialVersionUID = 2239821175446189806L;
 7     private String kind;
 8     private String name;
 9 
10     public Dog( String str) {
11         System.out.println(str);
12     }
13 
14     public String getKind() {
15         return kind;
16     }
17 
18     public void setKind(String kind) {
19         this.kind = kind;
20     }
21 
22     public String getName() {
23         return name;
24     }
25 
26     public void setName(String name) {
27         this.name = name;
28     }
29 
30 }
  1. View Code
  2. Order类代码如下:
1 public class Order implements Serializable {
 2 
 3     /**
 4      * 
 5      */
 6     private static final long serialVersionUID = 7441323999887439757L;
 7 
 8     private String orderNo;
 9     private String orderType;
10 
11     public Order( String str) {
12         System.out.println(str);
13     }
14 
15     public String getOrderNo() {
16         return orderNo;
17     }
18 
19     public void setOrderNo(String orderNo) {
20         this.orderNo = orderNo;
21     }
22 
23     public String getOrderType() {
24         return orderType;
25     }
26 
27     public void setOrderType(String orderType) {
28         this.orderType = orderType;
29     }
30 }
  1. View Code
  2. 执行类如下:
1 public class Test {
2     public static void main(String[] args) {
3         Person p = new Person();
4         Student stu = new Student();
5     }
6 }
  1. View Code
  2. 只实例化Person类,执行结果如下图:
  1. 结论:
  1. 初始化的总的顺序是:静态初始化-->非静态初始化-->构造器初始化。
  2. 静态初始化的顺序是:按代码中的顺序进行初始化,谁在前谁先初始化。如上面Person类中所示,虽然构造方法和非静态代码块在最前面,但是从上图的结果可以看出,还是先进行静态初始化。
  3. 非静态初始化的顺序和静态初始的顺序相同,谁在前谁先初始化。
  1. 只实例化Student类,执行结果如下:
  1. 结论:
  1.  初始化的顺序是:父类静态初始化-->子类静态初始化-->父类非静态初始化-->父类构造器初始化-->子类非静态初始化-->子类构造器初始化。
  1. 先实例化Person,再实例化Student类,执行结果如下:
  1. 结论:
  1. 初始化顺序大体上依然是【静态初始化-->非静态初始化-->构造器初始化】。
  2. 由于静态变量或代码块属于类,而不属于类的某个实例,其初始化动作只进行一次。在实例化Person类时静态变量或代码块已经初始化过了,因此在实例化Student类时,将不再初始化其父类中的静态变量或代码块。
  1. 总结
  1. 初始化的总体顺序:父类静态初始化---->子类静态初始化---->父类非静态初始化---->父类构造方法初始化---->子类非静态初始化---->子类构造方法初始化。
  2. 静态的初始化的顺序:按代码中的顺序进行初始化,谁在前谁先初始化。
  3. 非静态初始化的顺序和静态初始化的顺序一致,谁在前谁先初始化。
  4. 静态初始化只进行一次。