实例变量定义和实例块
我有以下代码 –
{s = "Hello";} String s;
这编译得很好,这意味着变量定义在实例阻塞之前执行。 但是,如果我使用以下代码,则不会编译(“错误:非法转发引用”)。
{s = "Hello"; String ss = s;} String s;
因此,在变量定义之前出现的实例块中,不可能在语句的右侧使用’s’的值。 对幕后发生的事情有一个明智的解释,还是这只是Java的特殊function?
PS我之前看过一个类似的问题,唯一的解释是它是Java的一个特性。 我写这篇文章是为了询问社区,这是否确实是这个问题的最后一句话。
JLS§8.3.3(“现场初始化期间的前向参考”)在这里阐述了一些内容:
使用在使用后以声明方式显示声明的实例变量有时会受到限制,即使这些实例变量在范围内也是如此。 具体来说,如果满足以下所有条件,则为编译时错误:
在使用实例变量之后,类或接口C中的实例变量的声明以文本forms出现;
在C的实例变量初始值设定项或C的实例初始值设定项中使用是一个简单的名称;
使用不在作业的左侧;
C是封闭使用的最内层类或接口。
第一颗子弹将适用于您的示例。
至于“为什么”部分,“为什么”通常是一个棘手的语言设计问题,但在这种情况下,他们有助于进一步向下添加这个注释:
上述限制旨在在编译时捕获循环或其他格式错误的初始化。
在第二种情况下,您将得到编译错误IllegalForwardReference,因为变量s
的使用不在赋值的左侧,并且JLS明确指出它是导致IllegalForwardReference错误的原因之一
我只能告诉你:编译器将所有初始化代码移动到构造函数体的末尾 (为每个构造函数重复代码)。 反编译一个例子就会显示出来。
所以,你必须意识到,通过这种方式,某些变量的声明顺序在将其作为右侧进行评估时很重要,即使在将其作为左侧进行评估时无关紧要。
摆脱这些不连贯性的一种方法是将范围“this”预先挂起到每个实例变量。
- Elasticsearch映射设置’not_analyzed’并在Java中按字段分组
- RxAndroid:在Schedulers.io()线程上更改UI
- appdata范围内无法更新文件存储 – 500内部服务器错误
- 持久保存@Embeddable的@ElementCollection(Google App Engine,datanucleus)
- 用Short和int重载
- Java中的协变返回类型
- 在GAE / J和JPA上使用@MappedSuperclass时,“字段jdoFieldFlags是冲突的”
- 翻转hex字符串
- 使用KeyGenParameterSpec.Builder等效替换KeyPairGeneratorSpec – 密钥库操作失败