【问题标题】:Static final field initialization from static initializer来自静态初始化器的静态最终字段初始化
【发布时间】:2014-10-06 17:28:30
【问题描述】:
为什么不能使用声明类作为限定符(以静态方式)从相应的静态初始化器访问静态最终字段?
起初,我以为这是一个 Eclipse 错误:
我还缺乏一些知识,因为静态初始化器不是我的日常工作。但是你瞧,这在没有类限定符的情况下可以正常工作:
为了完成我的测试系列,我在 bash 中试了一下:
导致同样的结果。
这就引出了最后一个问题:
从静态初始化块访问静态最终字段时,是否有任何理由禁止类限定符?
因为声明类之前没有初始化?
【问题讨论】:
标签:
java
static-initializer
【解决方案1】:
实际上,您可以从静态初始化器初始化静态字段。
但我认为(我不确定),您遇到了另一个问题。这里的问题是您(根据编译器)试图分配一个 final 字段。但是,您的真正意图不是分配它。您正在尝试初始化它。但是编译器没有得到这个。
当您调用 Test.I 之类的东西时,编译器会认为您正在尝试修改它之前可能已初始化的静态变量(即来自静态初始化程序)。编译器并不那么聪明,无法看到您实际上是在初始化变量,它只是解释您正在从一个类中分配一个静态变量,无论是 Test或者是Foo。
但是,如果您在没有 类限定符 的情况下调用它,编译器就会知道您正在尝试修改自己的静态变量,并且在静态初始化程序中,因此该操作对于 final 字段。
请,我希望我说得足够清楚,请注意,我不确定这种行为。
【解决方案2】:
为了在初始化块中初始化最终变量,应该使用变量的简单名称。即没有任何限定符的变量名。
在java语言规范中有如下说明
“同样,每个空白的 final 变量最多只能赋值一次;当对它进行赋值时,它肯定是未赋值的。这样的赋值被定义为当且仅当变量的简单名称之一时才会发生, 或其简单名称由此限定,出现在赋值运算符的左侧。Java 编译器必须执行特定的保守流分析,以确保对于空白最终变量的每个赋值,变量在赋值之前肯定是未赋值的;否则一定会出现编译时错误。”