静态域/域的初始化、静态代码块/构造代码块的实行、构造方法的调用 顺序

这5者的先后顺序中,有些顺序是跟Java源代码顺序有关的,有些无关的。

首先应该定义两个类,用于代表两种域的类型,这两个类的构造方法会打印信息,用于指示自身被实例化了。

class Field {
    public Field(int i) {
        System.out.println("B: 域引用第 " + i + " 次实例化");
    }
}

class StaticField {
    public StaticField(int i) {
        System.out.println("A: 静态域引用第 " + i + " 次实例化");
    }
}

 

1:静态的“东西”一定是比非静态的先执行的。

public class InitOrderTest {
    public static void main(String[] args) {
        Body b = new Body();
    }
}

class Body {
    // B
    {
        System.out.println("B: 构造代码块第1次");
    }
    Field f1 = new Field(1);
    {
        System.out.println("B: 构造代码块第2次");
    }
    {
        System.out.println("B: 构造代码块第3次");
    }
    Field f2 = new Field(2);

    // A
    static {
        System.out.println("A: 静态代码块第1次");
    }
    static StaticField sf1 = new StaticField(1);
    static {
        System.out.println("A: 静态代码块第2次");
    }
    static {
        System.out.println("A: 静态代码块第3次");
    }
    static StaticField sf2 = new StaticField(2);

    // C
    public Body() {
        System.out.println("C: 构造方法");
    }
}

 

A: 静态代码块第1次
A: 静态域引用第 1 次实例化
A: 静态代码块第2次
A: 静态代码块第3次
A: 静态域引用第 2 次实例化
B: 构造代码块第1次
B: 域引用第 1 次实例化
B: 构造代码块第2次
B: 构造代码块第3次
B: 域引用第 2 次实例化
C: 构造方法

即便Body类的B代码片段写在A片段前面,打印结果A还是在B前面,因为类需要先加载才能实例化,静态域和静态代码块会在类生命周期的“初始化”步骤中进行处理。

 

静态域和静态代码块算是“类"层次,域和构造代码块算是“对象”层次,同一层次的域和代码块顺序先后跟代码顺序一致,不存在一定是谁先处理的情况。

class Body {
    // B
    {
        System.out.println("B: 构造代码块第1次");
    }
    {
        System.out.println("B: 构造代码块第2次");
    }
    Field f1 = new Field(1);
    {
        System.out.println("B: 构造代码块第3次");
    }
    Field f2 = new Field(2);

    // A
    static {
        System.out.println("A: 静态代码块第1次");
    }
    static {
        System.out.println("A: 静态代码块第2次");
    }
    static StaticField sf1 = new StaticField(1);
    static {
        System.out.println("A: 静态代码块第3次");
    }
    static StaticField sf2 = new StaticField(2);

    // C
    public Body() {
        System.out.println("C: 构造方法");
    }
}

 

A: 静态代码块第1次
A: 静态代码块第2次
A: 静态域引用第 1 次实例化
A: 静态代码块第3次
A: 静态域引用第 2 次实例化
B: 构造代码块第1次
B: 构造代码块第2次
B: 域引用第 1 次实例化
B: 构造代码块第3次
B: 域引用第 2 次实例化
C: 构造方法

 

构造方法是这5者中最后执行的

class Body {
    // C
    public Body() {
        System.out.println("C: 构造方法");
    }

    // B
    {
        System.out.println("B: 构造代码块第1次");
    }
    Field f1 = new Field(1);
    {
        System.out.println("B: 构造代码块第2次");
    }
    {
        System.out.println("B: 构造代码块第3次");
    }
    Field f2 = new Field(2);

    // A
    static {
        System.out.println("A: 静态代码块第1次");
    }
    static StaticField sf1 = new StaticField(1);
    static {
        System.out.println("A: 静态代码块第2次");
    }
    static {
        System.out.println("A: 静态代码块第3次");
    }
    static StaticField sf2 = new StaticField(2);
}

 

A: 静态代码块第1次
A: 静态域引用第 1 次实例化
A: 静态代码块第2次
A: 静态代码块第3次
A: 静态域引用第 2 次实例化
B: 构造代码块第1次
B: 域引用第 1 次实例化
B: 构造代码块第2次
B: 构造代码块第3次
B: 域引用第 2 次实例化
C: 构造方法

 

posted @ 2017-06-27 16:30  Deolin  阅读(254)  评论(0编辑  收藏  举报