MENU

Java杂记(一)静态及非静态代码块执行顺序

June 10, 2018 • Code

前言:深入理解 Java 中静态块、静态语句、构造块及构造函数的执行顺序。

主要内容

栗子

class SuperClass {

    static SuperClass A = new SuperClass();

    static {
        System.out.println("B");
    }

    {
        System.out.println("C");
    }

    public SuperClass() {
        System.out.println("D");
    }

}

class SubClass extends SuperClass {

    static SubClass B = new SubClass();

    static {
        System.out.println("E");
    }

    {
        System.out.println("F");
    }

    public SubClass() {
        System.out.println("G");
    }

    public static void main(String[] args) {
        new SubClass();
    }
}

结果

解释

  • 执行顺序:静态块/静态成员变量 > Main 方法 > 构造块 > 构造函数。

  • 不同的静态块/静态成员变量按照出现的顺序执行,且只执行一次,因为静态块/静态成员变量属于,不属于实例对象,而类在 JVM 启动时加载,故只加载一次。

  • 构造块和构造函数属于实例对象,故实例化几次就执行几次代码块。

  • 子类会先执行父类的构造块和构造函数,再执行自己的构造块和构造函数。

针对上面栗子来说:

  1. 首先可以把同一个类的构造块和构造函数「绑定」在一起,绑定的意思是只要出现则会一起出现,即 C 和 D 以及 F 和 G。

  2. 先执照出现顺序执行父类 SuperClass 中的静态块/静态成员变量,再执行子类的静态块/静态成员变量。其中父类静态变量实例化了本类,故先出现 C 和 D,再按照顺序执行静态块,输出 B

    目前序列:CDB。

  3. 执行子类静态块/静态成员变量。由于子类静态变量实例化了本类,而子类实例化会先执行父类的实例化,故 static SubClass B = new SubClass() 一句会先执行父类的实例化,输出 C 和 D,再实例化子类本身,输出 F 和 G。最后再执行子类静态块,输出 E

    目前序列:CDBCDFGE。

  4. 静态部分执行完成后,再执行 Main 中的代码 new SubClass(),先实例化父类再实例化子类,输出 CDFG

    目前序列:CDBCDFGECDFG。

小结

通过一个综合的例子分析 Java 中各个部分代码的加载顺序,加深对 Java 中静态及非静态代码加载时机的理解。

Last Modified: July 9, 2018
Archives QR Code
QR Code for this page
Tipping QR Code