如何使 E1 += E2 非法,而 E1 = E1 + E2 是合法的?
我一直在阅读Bloch和Gafter的Java Puzzlers,并进入了拼图10(Tweedledee)。这个谜题的本质是
为变量提供声明,以便这是一个法律声明:
x
i
x = x + i;
但这不是:
x += i;
根据这本书,解决这个问题的方法看起来像这样:
Object x = "Buy ";
String i = "Effective Java!";
该书声称,在运算符中,只有当左侧表达式具有类型时,右侧表达式才能是任何类型。但是,我尝试运行此代码,并且它编译并运行没有任何问题。+=
String
然后我深入研究了Java语言规范。第 15.26.2 节讨论了两种情况:当左侧表达式是数组访问表达式时,当它不是数组访问表达式时。如果左侧操作数表达式不是数组访问表达式,则 JLS 不会说明左侧表达式是字符串。如果是这样,这部分表示:
如果 T 是引用类型,则它必须是 String。因为类 String 是最终类,所以 S 也必须是 String。因此,对于复合赋值运算符,有时简单赋值运算符不需要运行时检查。
❖ 数组组件的保存值和右侧操作数的值用于执行由复合赋值运算符(必然为 +=)指示的二进制运算(字符串串联)。如果此操作突然完成,则赋值表达式会出于同样的原因突然完成,并且不会发生赋值。
此处的 T 是在编译时确定的左侧操作数的类型,S 是选定的数组组件。所以我想我会把我的代码修改成这样:
Object[] x = {new Object()};
String i = "Effective Java!";
x[0] += i;
但是,即使此代码编译和运行也没有任何问题,即使甚至不是远程.new Object()
String
为什么会发生这种情况?这是否意味着Java编译器偏离了JLS?还有可能以某种方式解决原始难题吗?