简体   繁体   English

最终变量首先初始化

[英]final variable initialized first

I was reading the question here : Java : in what order are static final fields initialized? 我在这里阅读这个问题: Java:初始化静态最终字段的顺序是什么?

According to the answer 根据答案

"except that final class variables and fields of interfaces whose values are compile-time constants are initialized first ..." “除了最终的类变量和接口的字段,其值是编译时常量首先被初始化......”

I think this is not correct because the following will fail : 我认为这是不正确的,因为以下将失败:

static {
    String y = x;
}

public static final String x = "test";

In the static block, x is not recognized. 在静态块中,无法识别x Can anyone please comment if that answer is correct ? 如果答案是正确的,有人可以评论吗?

The order of initialization doesn't change the fact that the JLS doesn't let you refer to variables before they're declared in various cases. 初始化顺序不会改变JLS在各种情况下声明变量之前不允许引用变量的事实。 This is described in JLS§8.3.3 : 这在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). 使用声明在使用后以文本形式出现的类变量有时会受到限制,即使这些类变量在范围内(第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; 在使用类变量之后,类或接口C中的类变量声明以文本形式出现;

  • The use is a simple name in either a class variable initializer of C or a static initializer of C; 在C的类变量初始化程序或C的静态初始化程序中使用是一个简单的名称;

  • The use is not on the left hand side of an assignment; 使用不在作业的左侧;

  • C is the innermost class or interface enclosing the use. C是封闭使用的最内层类或接口。

That's why your code gets this compilation erorr: 这就是你的代码得到这个编译erorr的原因:

error: illegal forward reference 错误:非法转发参考

The statement that static fields that are constant variables are initialized first is indeed defined in JLS§12.4.2 : 首先初始化作为常量变量的静态字段的声明确实在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. 否则,记录当前线程正在进行C的Class对象初始化并释放LC的事实。

    Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1). 然后,初始化C的静态字段,它们是常量变量(§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. 接下来,按文本顺序执行类的类变量初始值设定项和类的静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样。

As you can see, constant variables are initialized in step 6, but others in step 9. 如您所见,常量变量在步骤6中初始化,但在步骤9中初始化。

This demonstrates the behavior: 这表明了这种行为:

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

That compiles, and outputs: 编译并输出:

test
TEST

In contast, if you change the x line so it's not constant anymore: 如果你更改了x行,那么它就不再是常数了:

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

It compiles, but then fails because x is null as of y = foo(); 它编译,但随后将失败,因为xnully = foo(); .


For the avoidance of doubt: I don't recommend using methods to initialize fields like that. 为避免疑义:我建议使用方法来初始化这样的字段。 :-) :-)

As this answer states: 正如这个答案所述:

... they are initialized in the order in which they appear in the source. ......它们按照它们出现在源中的顺序进行初始化。

You are absolutely right, your example fails, because you are trying to use a variable that is declared after the usage. 你是绝对正确的,你的例子失败了,因为你试图使用在使用之后声明的变量。 Since static block are executed in order of the source code, you are absolutely correct and should suggest and edit for that answer, because this statement is invalid: 由于静态块是按源代码的顺序执行的,因此您绝对正确,应该建议并编辑该答案,因为此语句无效:

except that final class variables ... are initialized first. 除了最后的类变量...首先被初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM