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

Java 类中静态块和静态变量的执行顺序是什么?,java,static,final,Java,Static,Final,可能重复: 为什么在初始化块中更新字符串变量而不是整数(即使先写入块) 我的输出是 static null 注意,字符串变量初始化只在我插入最后一个修饰符时发生在块之前。为什么会这样?为什么整数也不呢?我也将其声明为最终静态的它们是按照给定的顺序初始化的(字段和静态块),这就是为什么打印值为空,没有为静态块之后定义的静态字段分配任何内容。从JLS的开始,适当地剪切: 初始化C的步骤如下: 然后,初始化值为编译时常量表达式的接口的最终类变量和字段(§8.3.2.1、§9.3.1、§13.4.

可能重复:

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

我的输出是

static null

注意,字符串变量初始化只在我插入最后一个修饰符时发生在块之前。为什么会这样?为什么整数也不呢?我也将其声明为最终静态的

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

从JLS的开始,适当地剪切:

初始化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
即使将
x
y
设为final也不会影响这一点,因为它们仍然不是编译时常量

注意,字符串变量初始化只在我插入最后一个修饰符时发生在块之前

在这一点上,它是一个编译时常量,它的任何用法基本上都是内联的。此外,变量值在其他初始值设定项之前赋值,如上所述


JLS的定义编译时常量-它包括所有原语值和
字符串
,但不包括包装器类型,如
整数

,下面是对您问题的简短而直接的回答

静态变量

JVM
加载
时,执行静态变量;当调用
类的实例化或其
静态方法
时,加载

静态块或静态初始值设定项块

静态初始化程序块在调用其
静态方法
之前被初始化
类在调用其
静态方法
之前被实例化,甚至在使用其
静态变量
之前被初始化

///Edited Part/////strong>

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();
    }

}
以上内容将打印
静态1

原因是
JVM
将执行名为
常量折叠的优化过程,对常量变量进行预计算


此外,在您的情况下,的结果是
静态空值
原因
常量折叠
应用于原语类型,而不是包装器对象,在你的例子中是整数…

我很抱歉。仍然很困惑。是什么让字符串成为编译时常量,为什么整数不一样?@TariqIbrahim:我会在答案中编辑一个链接。谢谢。我现在已经理解了在这种情况下,块应该打印静态1,对吗?谢谢。这有助于清除很多东西]用什么编程语言?这是一个什么样的问题给定链接的副本?
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();
    }

}