类的初始化顺序

1. 单个类内的初始化顺序

我们运行一个测试类来查看类的初始化顺序

public class Test_01 {

    // 静态变量
    public static Test_02 staticField = new Test_02();

    // 变量
    public Test_03 field = new Test_03();

    // 静态初始化块
    static {
        System.out.println("静态初始化块");
    }
    // 初始化块
    {
        System.out.println("初始化块");
    }
    // 构造器
    public Test_01() {
        System.out.println("构造器");
    }

    public static void main(String[] args) {
       new Test_01();
    }
}
class Test_02{
    public Test_02() {
        System.out.println("静态变量");
    }
}
class Test_03 {
    public Test_03() {
        System.out.println("变量");
    }
}

代码输出结果为:

静态变量
静态初始化块
变量
初始化块
构造器

由此可知,单个类的类内初始化顺序为:(静态变量、静态初始化块)=>(变量、初始化块)=>构造器

但是有一个问题,静态变量和静态初始化块谁最先初始化呢?变量和初始化块又是谁先初始化呢?

我们变换一下测试类内代码的位置

public class Test_01 {
    // 静态初始化块
    static {
        System.out.println("静态初始化块");
    }
    // 初始化块
    {
        System.out.println("初始化块");
    }
    // 静态变量
    public static Test_02 staticField = new Test_02();

    // 变量
    public Test_03 field = new Test_03();

    // 构造器
    public Test_01() {
        System.out.println("构造器");
    }

    public static void main(String[] args) {
       new Test_01();
    }
}
class Test_02{
    public Test_02() {
        System.out.println("静态变量");
    }
}
class Test_03 {
    public Test_03() {
        System.out.println("变量");
    }
}

代码输出结果为:

静态初始化块
静态变量
初始化块
变量
构造器

由此可知,静态初始化块和静态变量、初始化块和变量之间的初始化顺序是由他们在类中定义的顺序决定的。

2. 继承情况下父类和子类的初始化顺序

我们来看下测试代码

 class Fu {
    // 静态变量
    public static String staticField = "父类--静态变量";

    // 变量
    public String field = "父类--变量";
     // 静态初始化块
     static {
         System.out.println(staticField);
         System.out.println("父类--静态初始化块");
     }
     // 初始化块
     {
         System.out.println(field);
         System.out.println("父类--初始化块");
     }
    // 构造器
    public Fu() {
        System.out.println("父类--构造器");
    }
}
public class Zi extends Fu {
    // 静态变量
    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 Zi() {
        System.out.println("子类--构造器");
    }
    // 程序入口
    public static void main(String[] args) {
        new Zi();
    }
}

代码输出结果为:

父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器

由结果可知,除了静态变量和静态初始化块,子类的变量都是在父类初始化之后再进行初始化。

为什么子类的静态变量和静态初始化块,会比父类的变量和初始化、构造器先进行初始化呢?

我们把程序入口main方法修改一下

 // 程序入口
 public static void main(String[] args) {

 }

修改后的代码输出结果为:

父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块

由结果可知,静态变量和静态代码块在main方法启动之后,子类和父类对象创建之前就已经初始化了

所以子类的静态变量和静态初始化块,会比父类的变量和初始化、构造器先进行初始化。

posted @ 2020-11-03 23:00  渺渺孤烟起  阅读(60)  评论(0)    收藏  举报