【问题标题】:Access to final field via getter before its initializing在初始化之前通过 getter 访问 final 字段
【发布时间】:2014-10-23 11:40:31
【问题描述】:

首先,这个问题与这些好问题有前向关系:

1) Use of uninitialized final field - with/without 'this.' qualifier

2) Why isn't a qualified static final variable allowed in a static initialization block?

但我会从另一个角度问它。请记住:上面提到的问题是关于使用Java 7 中的关键字this 访问final 字段的问题。

在我的问题中有类似的东西,但不一样。好吧,考虑下面的代码:

public class TestInit {
    final int a;
    {
        // System.out.println(a);   -- compile error
        System.out.println(getA());
        // a = a;                   -- compile error
        a = getA();
        System.out.println(getA());
    }
    private int getA() {
        return a;
    }
    public static void main(String[] args) {
        new TestInit();
    }
}

输出是:

0
0

正如你所看到的,这里有两个不清楚的地方:

  1. 还有另一种合法的方式来访问未初始化的final 字段:使用它的getter。
  2. 我们是否应该将a = getA(); 的分配视为空白最终字段的合法,并且它总是会根据JLS 为非final 字段分配其默认值?换句话说,它应该被视为预期的行为吗?

【问题讨论】:

  • 您链接的问题具有 JLS 规定的规则。他们没有说任何关于调用方法的内容,所以这些都是允许的。

标签: java compiler-errors


【解决方案1】:

您真正遇到的是编译器的推理能力。 对于您的第一个编译器错误,这会失败,因为编译器肯定知道 a 未分配。与第二个 a=a 相同(您不能从 a 分配,因为此时绝对没有分配)。 工作 a=getA() 的行是 a 的第一个、单一、明确的赋值,所以这很好(不管值来自哪里;getA() 的实现无关紧要,此时不评估) .

方法 getA() 是有效的,并且可以返回 a,因为实例初始化器已经明确地为 a 赋值。

这对人类来说是有意义的,但这不是编译器内置的推断。每个独立评估的块都是有效的。

【讨论】:

  • 哪个“静态初始化器”?抱歉,你在说什么?
  • 对不起,实例初始化程序(我已经编辑更正)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 2020-12-29
  • 2021-09-10
  • 2020-10-23
  • 2021-05-17
相关资源
最近更新 更多