繁体   English   中英

最终变量首先初始化

[英]final variable initialized first

我在这里阅读这个问题: Java:初始化静态最终字段的顺序是什么?

根据答案

“除了最终的类变量和接口的字段,其值是编译时常量首先被初始化......”

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

static {
    String y = x;
}

public static final String x = "test";

在静态块中,无法识别x 如果答案是正确的,有人可以评论吗?

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

使用声明在使用后以文本形式出现的类变量有时会受到限制,即使这些类变量在范围内(第6.3节)。 具体来说,如果满足以下所有条件,则为编译时错误:

  • 在使用类变量之后,类或接口C中的类变量声明以文本形式出现;

  • 在C的类变量初始化程序或C的静态初始化程序中使用是一个简单的名称;

  • 使用不在作业的左侧;

  • C是封闭使用的最内层类或接口。

这就是你的代码得到这个编译erorr的原因:

错误:非法转发参考

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

  1. 否则,记录当前线程正在进行C的Class对象初始化并释放LC的事实。

    然后,初始化C的静态字段,它们是常量变量(§4.12.4,§8.3.2,§9.3.1)。

...

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

如您所见,常量变量在步骤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

如果你更改了x行,那么它就不再是常数了:

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

它编译,但随后将失败,因为xnully = foo();


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

正如这个答案所述:

......它们按照它们出现在源中的顺序进行初始化。

你是绝对正确的,你的例子失败了,因为你试图使用在使用之后声明的变量。 由于静态块是按源代码的顺序执行的,因此您绝对正确,应该建议并编辑该答案,因为此语句无效:

除了最后的类变量...首先被初始化。

暂无
暂无

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

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