13

我一直在阅读 Bloch 和 Gafter 的 Java Puzzlers 并进入了谜题 10 (Tweedledee)。这个谜题的本质是

为变量提供声明,x这样i这是一个合法的声明:

x = x + i;

但这不是:

x += i;

根据这本书,解决方案看起来像这样:

Object x = "Buy ";
String i = "Effective Java!";

该书声称,在+=运算符中,只有当左侧表达式具有 type 时,右侧表达式才可以是任何类型String。但是,我尝试运行此代码,它编译并运行没有任何问题。

然后我深入研究了 Java 语言规范。第 15.26.2 节讨论了两种情况:左侧表达式是数组访问表达式时,以及不是。如果左侧操作数表达式不是数组访问表达式,则 JLS 不会说明左侧表达式是字符串。如果是,这部分适用:

如果 T 是引用类型,那么它必须是 String。因为 String 类是 final 类,所以 S 也必须是 String。因此,对于复合赋值运算符,从不需要简单赋值运算符有时需要的运行时检查。

❖ 数组组件的保存值和右手操作数的值用于执行复合赋值运算符(必须是+=)指示的二元运算(字符串连接)。如果此操作突然完成,则赋值表达式出于同样的原因突然完成并且不发生赋值。

这里的 T 是在编译时确定的左侧操作数的类型,S 是选定的数组组件。所以我想我会把我的代码修改成这样:

Object[] x = {new Object()};
String i = "Effective Java!";
x[0] += i;

但是即使这段代码编译和运行也没有任何问题,即使它甚至new Object()不是远程的String.

为什么会这样?这是否意味着 Java 编译器偏离了 JLS?还有可能以某种方式解决原来的难题吗?

4

3 回答 3

4

尝试使用 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. 版以来这是正确的(请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26之前的先决条件已删除)


只是一个小编辑:我看不到任何方法可以修复/解决 Java 7.0_10 中的难题

于 2013-01-08T17:06:46.490 回答
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
于 2013-01-08T15:40:50.473 回答
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;
于 2013-01-08T15:39:39.680 回答