当E1 = E1 + E2合法时,如何使E1 + = E2非法?

时间:2013-01-08 15:29:36

标签: java expression concatenation variable-assignment

我一直在阅读Bloch和Gafter的Java Puzzlers,并参与了拼图10(Tweedledee)。这个难题的本质是

  

为变量xi提供声明,以便这是一个法律声明:

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?是否仍然可以以某种方式解决原始难题?

3 个答案:

答案 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;
相关问题