java 类的初始化顺序

来源:互联网 发布:微星笔记本怎么样知乎 编辑:程序博客网 时间:2024/05/17 21:51

对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序以此是(静态变量、静态初始化块)>(变量、初始化块)>构造器。我们也可以通过下面的测试代码来验证这一点:

public class InitialOrderTest {

       //静态变量

       public static String staticField = "静态变量";

       //变量

       public String field = "变量";

       //静态初始化块

       static {

              System.out.println(staticField);

              System.out.println("静态初始化块");

       }

       //初始化块

       {

              System.out.println(field);

              System.out.println("初始化块");

       }

       //构造器

       public InitialOrderTest() {

              System.out.println("构造器");

       }

       public static void main(String[] args) {

              new InitialOrderTest();

       }

}


运行以上代码,我们会得到如下的输出结果:

1 静态变量

2 静态初始化块

3 变量

4 初始化块

5 构造器

这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:

class Parent {

       //静态变量

       public static String p_StaticField = "父类--静态变量";

       //变量

       public String p_Field = "父类--变量";

       //静态初始化块

       static {

              System.out.println(p_StaticField);

              System.out.println("父类--静态初始化块");

       }

       //初始化块

       {

              System.out.println(p_Field);

              System.out.println("父类--初始化块");

       }

       //构造器

       public Parent() {

              System.out.println("父类--构造器");

       }

}

public class SubClass extends Parent {

       //静态变量

       public static String s_StaticField = "子类--静态变量";

       //变量

       public String s_Field = "子类--变量";

       //静态初始化块

       static {

              System.out.println(s_StaticField);

              System.out.println("子类--静态初始化块");

       }

       //初始化块

       {

              System.out.println(s_Field);

              System.out.println("子类--初始化块");

       }

       //构造器

       public SubClass() {

              System.out.println("子类--构造器");

       }

       //程序入口

       public static void main(String[] args) {

              new SubClass();

       }

}

运行一下上面的代码,结果马上呈现在我们的眼前:  

1 父类--静态变量

2 父类--静态初始化块

3 子类--静态变量

4 子类--静态初始化块

5 父类--变量

6 父类--初始化块

7 父类--构造器

8 子类--变量

9 子类--初始化块

10 子类--构造器

现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。

那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于它们在类中出现的先后顺序。我们以静态变量和静态初始化块为例来进行说明。

静态数据的初始化是在类被装载的时候就被初始化,所以在继承中,因为在构造子类之前会先构造父类,这时就会现将父类的class文件加载到jvm中,一旦父类class文件被加载,就会初始化该类中的静态数据(静态变量和静态代码块),父类class文件加载完成接着加载子类的class文件,同理,子类的所有静态数据也被初始化。现在所有的class文件都被加载成功。接着开始初始化对象,从父类开始初始化,为了初始化对象,就要把类中的除静态数据以外的普通变量先初始化,这时普通变量初始化完成,然后是子类的普通变量初始化。再从父类开始,执行父类构造方法,子类构造方法。我发现类的初始化就是按照一个顺序进行:静态数据-->普通变量-->构造函数 。就算是多重继承还是这个顺序,从祖先父类到最下面的子类,先把所有的静态数据初始化。再回过头,从祖先父类到最下面的子类,初始化所有的普通变量。再回过头,从祖先父类到最面的子类,初始化构造器。