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:
正如您所看到的,这里有两个不清楚的事情:
- There is another legal way to access non-initialized
final
field: using its getter. - 还有另一种合法方式来访问非初始化的最终字段:使用其getter。
- 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 toJLS
? In other words, should it be considered as expected behaviour? - 我们应该考虑一个分配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.
对于看着它的人来说它是有道理的,但它不是编译器内置的推论。每个独立评估的块都是有效的。