以什么顺序执行的类中的静态块和静态变量?

时间:2012-09-16 16:07:48

标签: java static final

  

可能重复:
  Java static class initialization

为什么字符串变量在初始化块中更新而不是整数(即使先写入块)

class NewClass
{
    static 
    {
       System.out.println(NewClass.string+" "+NewClass.integer);
    }

    final static String string="static";
    final static Integer integer=1;

    public static void main(String [] args)//throws Exception
    {
    }
}

我的输出是

static null

P.S:还注意到只有当我插入final修饰符时,字符串变量初始化才会发生在块之前。为什么会这样?为什么不是整数呢?我已经宣布它为最终静态

3 个答案:

答案 0 :(得分:19)

从JLS的section 12.4.2开始,适当地剪断:

  

初始化C的过程如下:

     
      
  • 然后,初始化其值为编译时常量表达式的接口的最终类​​变量和字段(§8.3.2.1,§9.3.1,§13.4.9,§15.28)。

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

  •   

因此,对于非编译时常量,它不是“所有变量”的情况,而是“所有静态初始化器”,反之亦然 - 它们全部按文本顺序组合在一起。所以如果你有:

static int x = method("x");

static {
    System.out.println("init 1");
}

static int y = method("y");

static {
    System.out.println("init 2");
}

static int method(String name) {
    System.out.println(name);
    return 0;
}

然后输出为:

x
init 1
y
init 2

即使提出xy final也不会影响这一点,因为它们仍然不是编译时常量。

  

P.S:还注意到只有当我插入最终修饰符时,字符串变量初始化才会发生在块之前。

此时,它是一个编译时常量,并且它的任何使用基本上都是内联的。此外,变量值在其余的初始值设定项之前分配,如上所述。

JLS的

Section 15.28定义了编译时常量 - 它包括所有原始值和String,但包装类型,如Integer。< / p>

答案 1 :(得分:7)

这是一个简短直截了当的问题答案....

static Variable

静态变量在JVM 加载 Class时执行,而Class <时加载< 实例化或正在调用其static method

static Block or static Initializer Block

静态静态初始化程序块初始化 Class获取实例化 > <{strong>}之前<{>}和甚至在之前使用static method

/////////编辑部分/////////

static variable

上面会打印 class NewClass { final static String string = "static"; final static Integer integer = 1; static { System.out.println(NewClas.string + " " + NewClas.integer); } public static void main(String [] args) { // throws Exception new NewClas(); } }

原因是static 1将执行优化过程,称为JVM,执行常量变量的预计算。

此外,在您的情况下,结果Constant folding因为static null应用于原始类型而不是Wrapper对象,在您的情况下是整数......

答案 2 :(得分:1)

它们按给定的顺序(字段和静态块)初始化,这就是打印值为null的原因,没有为静态块之后定义的静态字段分配任何内容。