解释java编译顺序

时间:2016-05-25 13:59:41

标签: java jvm singleton

第一次进入A&C时,

v2为空,但如果我提出v2的声明&在instance之前初始化它将有一个值;这是为什么?

public class A {

    private static final String v1 = new String(new byte[]{'a', 'b'});

    private static A instance = new A();

    private static final String v2 = new String(new byte[]{'b', 'c'});

    private A() {
        System.out.printf("A c'tor\tv1 [%s]\tv2 [%s]\n", v1, v2);
    }

    public static void main(String[] args) {
        System.out.println("start main");
        new A();
        System.out.println("end main");
    }
}

输出:

    A c'tor v1 [ab] v2 [null]
    start main
    A c'tor v1 [ab] v2 [bc]
    end main

另外,如果我将v2的初始化更改为:

private static final String v2 = "ab";

它会初始化v2,输出为:

A c'tor v1 [ab] v2 [ab]
start main
A c'tor v1 [ab] v2 [ab]
end main

修改

第二部分的另一个测试:

public class A {

    private static final String v1 = new String(new byte[]{'a', 'b'});

    private static transient A instance = new A();

    private static final String v2 = new String(new byte[]{'b', 'c'});
    private static final String v3 = new String("ab");
    private static final String v4 = "ab";

    private A() {
        System.out.printf("A c'tor\tv1 [%s] v2 [%s] v3 [%s] v4 [%s]\n", v1, v2, v3, v4);
    }

    public static void main(String[] args) {
        System.out.println("start main");
        new A();
        System.out.println("end main");
    }
}

输出:

A c'tor v1 [ab] v2 [null] v3 [null] v4 [ab]
start main
A c'tor v1 [ab] v2 [bc] v3 [ab] v4 [ab]
end main

1 个答案:

答案 0 :(得分:3)

静态变量按照初始化类A时(在执行main之前)在源文件中出现的顺序进行初始化。

  • 第一个v1
  • then instance(打印A c'tor v1 [ab] v2 [null],因为它的初始化涉及创建A的实例) - 它在v2之前初始化,这就是v2仍为null的原因。
  • 然后是v2

初始化后,执行main方法,并生成接下来的3个输出行。在A方法中创建main的新实例会产生与前一个构造函数调用不同的输出,因为此时v1v2都被初始化。 / p>

编辑:

关于您更新的问题:

如果您关注initialization procedure in JLS 12.4.2

  
      
  1. 否则,记录当前线程正在进行C的Class对象初始化并释放LC的事实。然后,初始化接口的最终类变量和字段,其值为编译时常量表达式。
  2.         

    ...

         
        
    1. 接下来,执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,按文本顺序,就像它们是单个块一样。
    2.   

如您所见,其值为compile-time constant expressions的最终静态变量在其余静态变量之前初始化。因此,将v2的值更改为常量"ab"会导致v2instance变量之前初始化,这解释了不同的输出。