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

19

可能是重复问题:
Java静态类初始化

为什么字符串变量在初始化块中被更新而整数变量没有(尽管块写在第一位)?

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

另外注意到,只有在我插入final修饰符时,字符串变量的初始化才会在块之前发生。为什么是这样呢?为什么整数不也是一样呢?我已经将其声明为final static了。


用什么编程语言? - Paulo Merson
这怎么是给定链接的重复? - randomVariable
3个回答

21

来自JLS section 12.4.2,适当删节:

初始化C的过程如下:

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

  • 接下来,按文本顺序执行类的类变量初始化器和静态初始化器,或者接口的字段初始化器,就好像它们是一个单独的块。

因此,对于非编译时常量,不是“所有变量”然后“所有静态初始化器”,反之亦然 - 它们都在一起,按文本顺序排列。所以如果你有:

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:还注意到只有在插入final修饰符时,字符串变量初始化才会在块之前发生。

此时,它是编译时常量,并且任何对它的使用基本上都被内联。此外,在其余的初始化器之前赋值变量值,如上所示。
JLS的Section 15.28定义了编译时常量-它包括所有原始值和String,但不包括诸如Integer之类的包装类型。

很抱歉,我仍然感到困惑。是什么使字符串成为编译时常量,而整数却不同? - tr_quest
1
@TariqIbrahim:我会在答案中编辑一个链接。 - Jon Skeet

7
这里是对您问题的简短而直接的回答... static Variable
静态变量在JVM加载Class时执行,而Class会在其被实例化或其static method被调用时加载。 static Block or static Initializer Block
静态初始化块在Class被实例化或其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 将进行称为 常量折叠优化过程,对常量变量进行预计算。

此外,在您的情况下,结果static null,因为常量折叠仅适用于基本类型而不是包装对象,在您的情况下是 Integer...


在这种情况下,该代码块应该打印出静态 1,对吗? - tr_quest
谢谢,这帮助澄清了很多事情。 - tr_quest

1
它们按照给定的顺序进行初始化(字段和静态块),这就是为什么打印出来的值是null,因为在静态块之后定义的静态字段没有被赋值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接