Java中如何初始化静态final变量

7
public class Test {

    private static final int A;

    static {
        A = 5;
    }
}

这种初始化静态 final 变量 A 的方式可以正常工作。

public class Test {
    private static final int A;

    static {
        Test.A = 5;
    }   
}

这种方式会出现编译错误:"无法为最终变量 'A' 分配值"。
为什么会出现这种情况呢?

不确定,但可能是因为要执行 Test.A = 5,你需要一个 Test 的实例。而且在实例创建后你无法再赋值。 - Alper Akture
3
不需要一个 Test 实例。 - Jon Skeet
这是静态的主要特点,没有涉及到实例。 - takendarkk
2
我并不介意。像那样的代码非常罕见,你真的不需要它。我相信这是一些技术问题,与JLS定义事物的确切方式有关,可能与何时执行static块以及何时可以使用Test.A有关。尽管如此,这是一个有趣的发现,我也很好奇能否得到详细的答案。 - Zabuzard
1个回答

8

根据明确赋值规则的规定:

假设C是一个类,V是C中声明的空白static final成员字段,则:

  • 在C的最左边的枚举常量、静态初始化器(§8.7)或静态变量初始化器之前,V肯定未被分配(并且不确定已分配)。

  • 在除最左侧之外的C的枚举常量、静态初始化程序或静态变量初始化程序之前,如果V在先前的枚举常量、静态初始化程序或静态变量初始化程序之后[未]分配,则V [未]分配。

通俗易懂的解释:

使用静态初始化器通过引用其简单名称来初始化静态final字段是可以的,因为在初始化程序之后该字段肯定已经被赋值。实际上,在声明静态初始化器的类中有上下文,并且通过简单名称引用字段不执行任何非法分配;相反,您正在满足字段必须明确分配的要求。
使用静态初始化器通过引用其限定名称来初始化静态final字段是非法的,因为在引用其静态属性时必须初始化该类(在您的情况下,必须先初始化Test.A,并在初始化完成后将A分配为null的默认值)。

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