在定义字段之前无法引用字段,但仅限于您不符合条件
我发现发生以下代码使我的下巴下降:
public class MCVE { { // instance initializer System.out.println(test); // cannot reference a field before it is defined System.out.println(this.test); } private final String test = "wat"; }
System.out.println(test);
行System.out.println(test);
给出错误
在定义之前无法引用字段。
但是行System.out.println(this.test);
不是
当我符合条件时,为什么这不是错误?
正如许多这些问题一样,这是因为JLS这么说。
8.3.2.3初始化期间使用字段的限制
成员声明只有在成员是类或接口C的实例(分别为
static
)字段并且满足以下所有条件时才需要以文本方式显示:
- 用法发生在C的实例(分别是
static
)变量初始化器或C的实例(分别是static
)初始化器中。- 用法不在作业的左侧。
- 用法是通过一个简单的名称。
- C是封闭用法的最内层类或接口。
如果不满足上述四个要求中的任何一个,则为编译时错误。
在您的(失败)示例中,“简单名称”案例是未满足的条件。 限定使用(使用this
)是解决编译时错误的漏洞。
解释另一种方式:
在声明它们的行之前使用初始化块内的字段只能在表达式的左侧(即赋值),除非它们是合格的(在您的情况下是
this.test
)。
(更准确地解释为适应这个问题)
因为在创建lambda时可以捕获this
。 捕获test
不是(尚未定义)。 稍后,在lambda中你可以访问test
(通过this
)。