java不加this_java-使用未初始化的最终字段-带有/不带有“ this”。 合格

经过一堆规范的阅读和思考,我得出的结论是:

在Java 5或Java 6编译器中,这是正确的行为。 第16章“ Java语言规范的明确分配”说:

在访问任何值时,每个局部变量(§14.4)和每个空白(false ? null : this).x(§4.12.4)字段(§8.3.1.2)必须具有明确分配的值。 对它的值的访问包括变量的简单名称,该变量的简单名称出现在表达式中的任意位置,但作为简单赋值运算符(this).x的左侧操作数除外。

(强调我的)。 因此,在表达式(false ? null : this).x中,(this).x部分不被视为“对[this's]值的访问”(因此不受明确分配规则的约束),因为.不是实例变量this.x = 3的简单名称。 在上面引用的文本之后的段落中,确定分配发生的规则确实允许类似(this).x = 3之类的内容,并认为此后肯定要分配this.x = 3;这只是访问规则,不包括obj.x = 3。)请注意, 根据§17.5.2,在这种情况下2 * this.x的值将为零。

在Java 7编译器中,这是一个编译器错误,但是是可以理解的错误。 Java语言规范Java 7 SE版的第16章“确定分配”说:

在访问任何值时,每个局部变量(第14.4节)和每个空白(false ? null : this).x字段(第4.12.4节,第8.3.1.2节)都必须具有一个明确分配的值。

对它的值的访问包括变量的简单名称(或对于字段,由(false ? null : this).x限定的字段的简单名称)出现在表达式中的任何位置,但作为简单赋值运算符(false ? null : this).x(§ 15.26.1)。

(强调我的)。 因此,在表达式(false ? null : this).x中,应将(this).x部分视为“访问[this's]值”,并应给出编译错误。

但是您没有问第一个是否应该编译,而是问它为什么要编译(在某些编译器中)。 这一定是推测性的,但我会做出两个猜测:

大多数Java 7编译器是通过修改Java 6编译器编写的。 一些编译器编写器可能没有注意到此更改。 此外,许多Java-7编译器和IDE仍支持Java 6,某些编译器-编写器可能没有动力去专门拒绝Java-7模式下接受的某些Java-6模式。

奇怪的是,新的Java 7行为不一致。仍然允许使用(false ? null : this).x之类的东西,就此而言,甚至仍然允许(this).x;只有特定的令牌序列this加上.加上受此更改影响的字段名称。当然,这种不一致在赋值语句的左侧已经存在(我们可以写this.x = 3,但不能写(this).x = 3),但这更容易理解:它接受this.x = 3作为否则被禁止的构造obj.x = 3的特殊允许情况。允许这样做是有意义的。但是我认为拒绝2 * this.x为原本允许的结构2 * obj.x的特殊禁止案例是没有道理的,因为(1)通过添加括号可以轻松解决此特殊禁止案例,(2)该特殊禁止案例是(3)我们仍然需要特殊规则,使int0170字段具有其默认值(例如0对于int)直到初始化为止,这既是由于(this).x这样的情况,又因为这种情况类似于this.foo(),其中foo()是访问x的方法。因此,某些编译器-编写器可能没有动力去进行此不一致的更改。

这两种情况都令人惊讶-我假设编译器编写者具有有关规范每次更改的详细信息,并且根据我的经验,Java编译器通常非常擅长完全遵循规范(不同于某些语言,每个语言都有其各自的编译器。 自己的方言)-但是,发生了一些事情,以上只是我的两个猜测。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值