我有以下代码 -
{s = "Hello";}
String s;
这编译得很好,这意味着变量定义在实例阻塞之前执行。 但是,如果我使用以下代码,则不会编译(“错误:非法转发引用”)。
{s = "Hello"; String ss = s;}
String s;
因此,在变量前面的实例块中,不可能在语句的右侧使用's'的值 定义。对幕后发生的事情有一个明智的解释,还是这只是Java的特殊功能?
P.S。我之前看过一个类似的问题,唯一的解释是它是Java的一个特性。 我写这篇文章是为了询问社区,这是否确实是这个问题的最后一句话。
答案 0 :(得分:3)
JLS §8.3.3 ("Forward References During Field Initialization")在这里阐明了一些亮点:
使用在使用后以声明方式显示声明的实例变量有时会受到限制,即使这些实例变量在范围内也是如此。具体来说,如果满足以下所有条件,则为编译时错误:
在使用实例变量后,类或接口C中的实例变量声明以文本形式出现;
在C的实例变量初始值设定项或C的实例初始值设定项中,use是一个简单的名称;
使用不在作业的左侧;
C是封闭使用的最里面的类或接口。
第一颗子弹将适用于你的例子。
至于“为什么”部分,“为什么”通常是一个棘手的问题,语言设计,但在这种情况下,他们有助于进一步向下添加这个说明:
上述限制旨在在编译时捕获循环或其他格式错误的初始化。
答案 1 :(得分:0)
在第二种情况下,您将收到编译错误IllegalForwardReference,因为变量s
的使用不在赋值的左侧,而JLS明确指出它是导致IllegalForwardReference错误的原因之一
答案 2 :(得分:0)
我可以告诉你:编译器将所有初始化代码移动到构造函数的末尾'正文(为每个构造函数重复代码)。反编译一个例子会显示出来。
所以,你必须意识到,通过这种方式,某些变量的声明顺序在将其评估为右侧时很重要,即使在将其评估为左侧时并不重要。
摆脱这些不连贯性的一种方法是预先扩大范围"这个"到每个实例变量。