Mal*_*olm 12 java expression concatenation variable-assignment
我一直在阅读Bloch和Gafter的Java Puzzlers并得到了拼图10(Tweedledee).这个难题的本质是
为变量提供报关单
x
和i
这样的,这是一个法律声明:Run Code Online (Sandbox Code Playgroud)x = x + i;
但这不是:
Run Code Online (Sandbox Code Playgroud)x += i;
根据这本书,解决方案看起来像这样:
Object x = "Buy ";
String i = "Effective Java!";
Run Code Online (Sandbox Code Playgroud)
该书声称,在+=
操作符中,只有当左手表达式具有类型时,右手表达式才可以是任何类型String
.但是,我尝试运行此代码,它编译并运行没有任何问题.
然后我挖掘了Java语言规范.第15.26.2节讨论了两种情况:当左侧表达式是数组访问表达式时,何时不是.如果左侧操作数表达式不是数组访问表达式,那么JLS没有说左手表达式是String.如果是,这部分应用:
如果T是引用类型,则它必须是String.因为类String是最终类,所以S也必须是String.因此,复合赋值运算符永远不需要简单赋值运算符有时需要的运行时检查.
❖数组组件的保存值和右侧操作数的值用于执行复合赋值运算符指示的二进制运算(字符串连接)(必须为+ =).如果此操作突然完成,则赋值表达式会因同样的原因突然完成,并且不会发生任何赋值.
这里的T是在编译时确定的左操作数的类型,S是所选的数组组件.所以我认为我会将我的代码修改为:
Object[] x = {new Object()};
String i = "Effective Java!";
x[0] += i;
Run Code Online (Sandbox Code Playgroud)
但即使这个代码编译和运行也没有任何问题,即使它甚至new Object()
不是远程的String
.
为什么会这样?这是否意味着Java编译器偏离了JLS?是否仍然可以以某种方式解决原始难题?
尝试使用 javac < 1.4.2,它也可以在那里工作。
这是不同版本之间的变化。1.4.2 的更改(x += i;之前允许,此后不允许):
https://bugs.java.com/bugdatabase/view_bug ?bug_id=4642850
这是正确的,因为 JLS 2. 版本定义了:
所有复合赋值运算符都要求两个操作数均为基本类型,+= 除外,如果左侧操作数为 String 类型,则右侧操作数可以为任何类型。
7 的更改(x += i;之前不允许,此后允许):
https://bugs.java.com/bugdatabase/view_bug ?bug_id=4741726
自 JLS 3. 版本以来这是正确的(请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26删除了先前的先决条件)
只是一个小编辑:我没有看到任何方法来修复/解决 Java 7.0_10 中的难题