java - 最终变量首先初始化

标签 java static initialization

我在这里阅读问题:Java : in what order are static final fields initialized?

根据回答

"except that final class variables and fields of interfaces whose values are compile-time constants are initialized first ..."

我认为这是不正确的,因为以下将失败:

static {
    String y = x;
}

public static final String x = "test";

在静态 block 中,x 不被识别。如果答案正确,任何人都可以发表评论吗?

最佳答案

初始化 的顺序不会改变 JLS 不允许您在各种情况下声明变量之前引用变量的事实。这在 JLS§8.3.3 中有描述。 :

Use of class variables whose declarations appear textually after the use is sometimes restricted, even though these class variables are in scope (§6.3). Specifically, it is a compile-time error if all of the following are true:

  • The declaration of a class variable in a class or interface C appears textually after a use of the class variable;

  • The use is a simple name in either a class variable initializer of C or a static initializer of C;

  • The use is not on the left hand side of an assignment;

  • C is the innermost class or interface enclosing the use.

这就是为什么您的代码会出现此编译错误:

error: illegal forward reference

作为常量变量的静态字段先初始化的说法确实定义在JLS§12.4.2中:

  1. Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.

    Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).

...

  1. Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.

如您所见,常量变量在第 6 步中初始化,而其他变量在第 9 步中初始化。

这演示了行为:

public class Example {
    static String y;
    static  {
         y = foo();
    }

    static String foo() {
        return x.toUpperCase();
    }

    public static final String x = "test";

    public static void main(String[] args) throws Exception {
        System.out.println(x);
        System.out.println(y);
    }
}

编译并输出:

test
TEST

In contast, if you change the x line so it's not constant anymore:

public static final String x = Math.random() < 0.5 ? "test" : "ing";

它编译,但随后失败,因为从 y = foo(); 开始,xnull


为避免疑义:我建议使用方法来初始化这样的字段。 :-)

关于java - 最终变量首先初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57168984/

相关文章:

java - 修改函数无法打印预期结果

java - Eclipse 控制台和 Java 堆栈跟踪颜色

java.lang.OutOfMemoryError : Java heap space on startup 错误

android - 我收到错误,使封闭方法 "static"或从 android 中的 SonarLint 中删除此集

objective-c - 从其他已经初始化的类中调用NSView

iphone - 关于覆盖 init 函数的几个问题

java - OpenGL glfwInit()自动执行?

java - 抛出异常的 Java 方法是否有特定的命名约定?

C++ 初始化静态常量结构变量

php静态函数