Java 之初始化顺序

0 前言

本文通过拆分类似概念之间的初始化顺序,帮助大家彻底记住初始化的顺序

1. 父类和子类间的初始化顺序

示例代码:

public class Father {
    public Father() {
        System.out.println("father");
    }

    public static void main(String[] args) {
        grandson grandson = new grandson();
    }
}
class son extends Father {
    public son() {
        System.out.println("son");
    }
}
class grandson extends son{
    public grandson() {
        System.out.println("grandson");
    }
}

输出结果:

father
son
grandson

结论:
当存在父类时,先初始化父类构造函数,如果父类还有父类,再初始父类的父类构造函数,依次类推。

2. 构造函数、静态变量和实例变量的初始化顺序

示例代码:

public class Var {
    public Var() {
        printInit("structor");
    }
    public int j = printInit("Init");

    public static int i = printInit("static Init");

    static int printInit(String s) {
        System.out.println(s);
        return 0;
    }

    public static void main(String[] args) {
        Var var = new Var();
    }
}

输出结果:

static Init
Init
structor

结论:
静态变量 -> 实例变量 -> 结构体

3. 静态语句块和静态变量的初始化顺序

示例代码:

public class StaticCompare {

    public static int i = 1;

    static {
        i = 2;
        j = 2;
    }

    public static int j = 1;

    public static void main(String[] args) {
        System.out.println("i = " + StaticCompare.i);
        System.out.println("j = " + StaticCompare.j);
    }

}

输出结果:

i = 2
j = 1

结论:
静态语句块和静态变量按代码顺序执行,谁在前面谁先执行

4. 普通语句块和实例变量的初始化顺序

示例代码:

public class VarCompare {
    public int i = 1;

    {
        i = 2;
        j = 2;
    }

    public int j = 1;

    public static void main(String[] args) {
        VarCompare varCompare = new VarCompare();
        System.out.println("i = " + varCompare.i);
        System.out.println("j = " + varCompare.j);
    }
}

输出结果:

i = 2
j = 1

结论:
普通语句块和实例变量按代码顺序执行,谁在前面谁先执行

5. 总结

先做个小结,现在已经测试的顺序是:
静态变量(静态语句块) -> 实例变量(普通语句块) -> 构造函数
父类构造函数 -> 子类构造函数
接下来需要知道的是,当它们同时存在,是什么顺序?

5. 全部的初始化顺序

示例代码:

public class AllSequence extends father{
    public static int i = printInit("子类静态变量 i");

    public int j = printInit("子类实例变量 j");

    AllSequence(){
        System.out.println("子类构造函数");
    }

    public static void main(String[] args) {
        AllSequence allSequence = new AllSequence();
    }
}

class father {
    public static int i = printInit("父类静态变量 i");

    public int j = printInit("父类实例变量 j");

    father(){
        System.out.println("父类构造函数");
    }

    static int printInit(String s) {
        System.out.println(s);
        return 1;
    }
}

输出结果:

父类静态变量 i
子类静态变量 i
父类实例变量 j
父类构造函数
子类实例变量 j
子类构造函数

结论:
当存在继承关系时,初始化顺序为:

  1. 父类(静态变量、静态语句块)
  2. 子类(静态变量、静态语句块)
  3. 父类(实例变量、普通语句块)
  4. 父类(构造函数)
  5. 子类(实例变量、普通语句块)
  6. 子类(构造函数)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章