在定义字段之前无法引用字段,但仅限于您不符合条件

我发现发生以下代码使我的下巴下降:

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 )。