我一直在阅读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不会说左手表达式是String。如果是,这部分应用:
如果T是引用类型,则它必须是String。因为类String是一个 final类,S也必须是String。因此运行时检查即是 有时需要简单赋值运算符 复合赋值运算符。
❖数组组件的保存值和右侧的值 操作数用于执行二进制操作(字符串连接) 由复合赋值算子表示(必然 + =)。如果此操作突然完成,则为赋值表达式 由于同样的原因突然完成,没有任何分配。
这是在编译时确定的左侧操作数的类型,S是所选的数组组件。所以我认为我会将我的代码修改为:
Object[] x = {new Object()};
String i = "Effective Java!";
x[0] += i;
但即使new Object()
甚至远远不是String
,即使这段代码也会编译并运行没有任何问题。
为什么会这样?这是否意味着Java编译器偏离了JLS?是否仍然可以以某种方式解决原始难题?
答案 0 :(得分:3)
尝试使用javac< 1.4.2,它也会在那里工作。
这是不同版本之间的变化。
1.4.2的变化(x + = i;允许之前,而不是之后):
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4642850
哪个是正确的,因为JLS 2.版本定义了:
所有复合赋值运算符都要求两个操作数都是原始类型, 除了+ =,它允许右手操作数为左手的任何类型 操作数的类型为String。
7的变化(x + = i;之前不允许,允许自之后):
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4741726
这是正确的,因为JLS 3. edition(请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26删除了上一个先决条件)
只是一个小编辑:我没有看到任何方法来解决/解决Java 7.0_10中的难题
答案 1 :(得分:2)
我有以下内容,它将给定的解决方案显示为正确的答案:
public class testIt
{
public static void main(String args[])
{
new testIt();
}
public testIt()
{
Object x = "Buy";
String i = "Effective Java!"
x += i;
x = x + i;
}
}
当我编译这个时,我得到了
testIt.java: incompatible types
found: java.lang.Object
required: java.lang.String;
x += i;
^
1 error
答案 2 :(得分:0)
在Java 6中,您可以说
Object x = 1;
String i = "i";
x = x + i; // compiles
x += i; // doesn't compile in Java 6, but does in Java 7.
System.out.println(x);
为什么会这样?
与
相同x[0] = x[0] + i;
使用Java 7编译
Object[] x = {new Object()};
String i = "Effective Java!";
x[0] += i;
System.out.println(x[0]);
打印
java.lang.Object@a62b39fEffective Java!
但不适用于Java 6更新37
Error:Error:line (25)java: src\Main.java:25: incompatible types
found : java.lang.Object
required: java.lang.String
这是否意味着Java编译器偏离了JLS?
我怀疑这意味着Java 6不遵循当前的JLS。它可能符合旧版本。
是否有可能以某种方式解决原始难题?
有一个提示。这个编译
char ch = '0';
ch *= 1.1;
这不是
char ch = '0';
ch = ch * 1.1;