在初始化之前通过getter访问最终字段

时间:2022-07-16 09:44:16

First of all, this question has forward relation to these nice questions:

首先,这个问题与这些好问题有着前瞻性的关系:

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

1)使用未初始化的最终字段 - 有/没有'这个'。预选赛

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

2)为什么静态初始化块中不允许合格的静态最终变量?

But I will ask it in slightly another angle of view. Just to remember: mentioned questions above were asked about access to final fields using keyword this in Java 7.

但我会以另一种视角来问它。请记住:上面提到的问题是在Java 7中使用关键字this询问有关最终字段的访问权限。

In my question there is something similar, but not the same. Well, consider the following code:

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

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

And output is:

输出是:

0
0

As you can see there are two unclear things here:

正如您所看到的,这里有两个不清楚的事情:

  1. There is another legal way to access non-initialized final field: using its getter.
  2. 还有另一种合法方式来访问非初始化的最终字段:使用其getter。
  3. Should we consider that an assigment a = getA(); as legal for blank final field and that it will always assign to it its default value like for non-final field according to JLS? In other words, should it be considered as expected behaviour?
  4. 我们应该考虑一个分配a = getA();作为空白最终字段的合法,并且它将始终根据JLS为其分配默认值,如非最终字段?换句话说,它应该被视为预期的行为吗?

1 个解决方案

#1


0  

What you're really running into is the inference ability of the compiler. For your first compiler error, that fails because the compiler definitely knows a is not assigned. Same with the second a=a (you can't assign from a because it's definitely not assigned at that point). The line that works a=getA() is a first, single, definite assignment of a, so that's fine (regardless where the value comes from; the implementation of getA() doesn't matter and isn't assessed at this point).

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

The method getA() is valid and can return a because the instance initializer has definitely assigned a value to a.

方法getA()有效并且可以返回a,因为实例初始值设定项已明确为a赋值。

It makes sense to a human looking at it, but it's not an inference built into the compiler. Each block, independently evaluated, is valid.

对于看着它的人​​来说它是有道理的,但它不是编译器内置的推论。每个独立评估的块都是有效的。

#1


0  

What you're really running into is the inference ability of the compiler. For your first compiler error, that fails because the compiler definitely knows a is not assigned. Same with the second a=a (you can't assign from a because it's definitely not assigned at that point). The line that works a=getA() is a first, single, definite assignment of a, so that's fine (regardless where the value comes from; the implementation of getA() doesn't matter and isn't assessed at this point).

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

The method getA() is valid and can return a because the instance initializer has definitely assigned a value to a.

方法getA()有效并且可以返回a,因为实例初始值设定项已明确为a赋值。

It makes sense to a human looking at it, but it's not an inference built into the compiler. Each block, independently evaluated, is valid.

对于看着它的人​​来说它是有道理的,但它不是编译器内置的推论。每个独立评估的块都是有效的。