Java 在定义字段之前无法引用该字段,但仅当您不';我没有资格
我发现以下代码的出现让我大吃一惊:Java 在定义字段之前无法引用该字段,但仅当您不';我没有资格,java,initialization,syntax-error,Java,Initialization,Syntax Error,我发现以下代码的出现让我大吃一惊: 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"; } 行
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(测试)代码>正在给出错误
在定义字段之前无法引用该字段
但是行System.out.println(this.test)代码>是不是
为什么在我对其进行限定时这不会出错?因为在创建lambda时可以捕获此
。捕获测试
未定义(尚未定义)。不过,稍后,在lambda中,您可以访问测试(通过此
)。与这些问题一样,这是因为
8.3.2.3初始化期间对字段使用的限制
仅当成员是类或接口C的实例(分别为静态
)字段且满足以下所有条件时,成员声明才需要在使用前以文本形式出现:
- 该用法出现在C的实例(分别为
static
)变量初始值设定项或C的实例(分别为static
)初始值设定项中
- 用法不在作业的左侧
- 用法是通过一个简单的名称
- C是包含用法的最内层类或接口
如果上述四项要求中的任何一项未得到满足,则为编译时错误。
在您的(失败的)示例中,“简单名称”案例是未满足的条件。限定用法(使用this
)是解决编译时错误的漏洞
初始化块中声明字段的行之前的字段只能在表达式(即赋值)的左侧使用,除非它们是限定的(在您的示例中是this.test
)
(为了更贴切地适应这个问题而进行解释)这个问题不是lambdas特有的,实例初始值设定项也会有同样的问题。但是,普通构造函数不会有此问题。您可以将private final Runnable r=()->{
更改为{
,并将面临相同的行为。没有涉及构造函数…您想说明什么?您还可以将Runnable lambda更改为字符串字段:private final String test2=test;
生成相同的结果(<代码> String Test2=这个测试。 Works)“仍然有点困惑:它会打印“WAT”还是“”,以防我们删除不合格行并运行lambda?我看到,正如Matt指出的。我猜我对C++是如何做的感到困惑,它让您控制这个或测试是否会被捕获(通过值等)。。lambda似乎与此无关。当在lambda之前创建一个新字段时,以合格的方式访问测试也会起作用。不,创建lambda会导致在创建时捕获。我不认为字段在这方面很重要。在最终和成员初始化中有严格的顺序。lambda应该捕获this
在这两种情况下(假设另一种有效,可以通过将声明移到lambda之前获得)。正如在关于这个问题的两条评论中所指出的:这个问题不是lambdas特有的。我想我误解了Lambda捕获,我假设它是捕获时的值捕获,而不是通过这个。我同意这就是非限定实例不起作用的原因,但限定实例起作用的原因是不正确的。这不是一个循环le,但它根本不是在初始化期间访问测试。@ChristophenRoezbek限定引用特别有效,因为JLS这么说。它将如何工作?它将访问什么值?@ChristophenRoezbek java不是一种解释语言。我不得不说,它是在初始化期间访问的,因为这是一个小规范al,将“简单名称”转换为“限定名称”,因此不属于您在此处尝试的访问规则。@Christopher Roezbek只有一个可能的答案。