无法编译(有illegal forward reference错误),正如人们所期望的那样:
class test {
int x = x + 42;
}
Run Code Online (Sandbox Code Playgroud)
但这有效:
class test {
int x = this.x + 42;
}
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?在后一种情况下分配了什么?
Zho*_*gYu 18
x在x初始化期间发现并禁止所有访问都太困难了.例如
int x = that().x; | int x = getX();
|
Test that(){ return this; } | int getX(){ return x; }
Run Code Online (Sandbox Code Playgroud)
规范在"通过简单名称访问"时停止,并且不会尝试更全面.
在另一节"定义分配"中,规范做了类似的事情.例如
public class Test
{
static final int y;
static final int z = y; // fail, y is not definitely assigned
static{ y = 1; }
}
public class Test
{
static final int y;
static final int z = Test.y; // pass... because it's not a simple name
static{ y = 1; }
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,"Definite Assignment"特别提到了this.x相当于x
(或者,对于字段,由此限定的字段的简单名称)
该条款也可以添加到NPE引用的部分.
- 用法是通过简单的名称(或由此限定的简单名称)
但最终,在编译时不可能分析对字段的所有可能的使用/访问.
NPE*_*NPE 17
简介:两个初始值设定项都访问尚未初始化的字段(因此仍然具有默认值零).由于这可能是编程错误,因此该语言禁止这种访问的一些简单形式.但是,它并没有禁止更复杂的形式.
该行为符合JLS,特别是§8.3.2.3.初始化期间使用字段的限制
成员声明只有在成员是
static类或接口的实例(分别)字段C并且满足以下所有条件时才需要以文本方式显示:
用法发生在C的实例(分别
static)变量初始化器或C的实例(分别static)初始化器中.用法不在作业的左侧.
用法是通过一个简单的名称.
C是封闭用法的最内层的类或接口.
第一个示例满足所有四个条件,因此无效.第二个例子不满足第三个条件(this.x不是一个简单的名字),因此可以.
事件的整体顺序如下:
因此,如果初始化程序引用稍后出现在类定义中(或字段本身)的字段,则它将看到该其他字段的默认值.这可能是编程错误,因此§8.3.2.3明确禁止.
如果您绕过§8.3.2.3,例如,使用this.向前引用字段,您将看到默认值(零为int).因此,以下内容定义明确,并保证设置x为42:
class test {
int x = this.x + 42;
}
Run Code Online (Sandbox Code Playgroud)