Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何制作E1+;=E2非法,而E1=E1+;E2合法吗?_Java_Expression_Concatenation_Variable Assignment - Fatal编程技术网

Java 如何制作E1+;=E2非法,而E1=E1+;E2合法吗?

Java 如何制作E1+;=E2非法,而E1=E1+;E2合法吗?,java,expression,concatenation,variable-assignment,Java,Expression,Concatenation,Variable Assignment,我一直在阅读Bloch和Gafter的Java拼图游戏,并阅读了拼图10(Tweedledee)。这个难题的实质是 为变量x和i提供声明,使其成为法律声明: x = x + i; 但这不是: x += i; 根据这本书,解决方案如下: Object x = "Buy "; String i = "Effective Java!"; 这本书声称,在+=操作符中,只有当左侧表达式的类型为字符串时,右侧表达式才可以是任何类型。然而,我尝试运行这段代码,它编译并运行时没有任何问题 然后我深入研究了

我一直在阅读Bloch和Gafter的Java拼图游戏,并阅读了拼图10(Tweedledee)。这个难题的实质是

为变量
x
i
提供声明,使其成为法律声明:

x = x + i;
但这不是:

x += i;
根据这本书,解决方案如下:

Object x = "Buy ";
String i = "Effective Java!";
这本书声称,在
+=
操作符中,只有当左侧表达式的类型为
字符串时,右侧表达式才可以是任何类型。然而,我尝试运行这段代码,它编译并运行时没有任何问题

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

如果T是引用类型,则它必须是字符串。因为类字符串是一个 最后一个类,S也必须是字符串。因此,运行时检查 有时,简单赋值运算符是必需的,但对于 复合赋值运算符

❖ 数组组件的保存值和右侧 操作数用于执行二进制操作(字符串串联) 由复合赋值运算符指示(必要时 +=). 如果此操作突然完成,则赋值表达式 由于相同的原因突然完成,并且没有分配发生

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

Object[] x = {new Object()};
String i = "Effective Java!";
x[0] += i;
但是,即使这段代码编译和运行没有任何问题,即使
newobject()
甚至不是一个
字符串

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

在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;
用Java7编译

Object[] x = {new Object()};
String i = "Effective Java!";
x[0] +=  i;
System.out.println(x[0]);
印刷品

java.lang.Object@a62b39fEffective Java!
但不适用于Java6更新37

    Error:Error:line (25)java: src\Main.java:25: incompatible types
found   : java.lang.Object
required: java.lang.String
这是否意味着Java编译器偏离了JLS

我怀疑这意味着Java6没有遵循当前的JLS。它可能遵守了一个旧版本

还有可能以某种方式解决最初的难题吗

有一个暗示。这就编译了

char ch = '0';
ch *= 1.1;
这是不可能的

char ch = '0';
ch = ch * 1.1;

我有以下内容,它显示了给定的解决方案作为正确答案:

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

尝试使用javac<1.4.2,它在那里也可以工作

这是不同版本之间的变化。 1.4.2(x+=i;允许之前更改,不允许之后更改):

这是正确的,因为JLS 2。定义的版本:

所有复合赋值运算符都要求两个操作数均为基元类型, 除了+=,它允许右操作数为任何类型,如果左操作数为 操作数的类型为字符串

7的更改(x+=i;之前不允许,之后允许):

这是正确的,因为JLS 3。版本(请参阅前面的先决条件已删除)



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

您是否尝试过创建一个对象来覆盖
toString
以打印到stdout/stderr?您确定应该编译哪个吗?或者这本书有打字错误。例如,如果x和i是字节,则
x+=i有效,但
x=x+i不是。您确定您实际测试了
x+=i
而不是
i+=x
?我的意思是,(String)+=(Object)将很容易编译,而(Object)+=(String)将不会编译。@Tintorius您不必创建一个对象来打印到标准输出,结果是一个如下所示的字符串:
java.lang。Object@5a4b4b50Effective爪哇。所以连接发生得很好。@Malcolm:我只是想用它来进行(惰性)调试,看看Java实际上在做什么。在他的例子中有(Object)+=(String)。您的建议仅适用于反向:(String)+=(Object)(当Object转换为String时)。@DmitryZaitsev在Java7中有效。您尝试过哪种版本的Java?@DmitryZaitsev,这表明它可能是Java 6中的JLS错误。相反,JDK7似乎不遵守JLS,因为JLS要求左侧的值在数组中时为字符串,并且它仍然编译和运行没有问题。虽然作为一名程序员,我认为这种行为实际上比JLS中的更好,因为它与
x+I
一致。关于最初的谜题,我正在寻找
+=
是非法的,而
+
是合法的案例。我知道另一种情况是由于隐藏强制转换而发生的,我对此不感兴趣。您使用的是哪个版本的Java?这在Java 7上编译和运行。然后Java 7忽略JLS。但是JLS是否说
x+=i
不应该工作?我认为,JLS只需要数组中的
String
,在所有其他情况下都不重要。JLS只是说,
首先,对左侧操作数求值以生成一个变量
,然后
使用左侧变量的保存值和右侧操作数的值来执行复合赋值运算符
指示的二进制运算,这与
x+i
没有什么不同。关于左手表达式是字符串,没有任何说明。好的,我看到了JLS中的更改,但是数组访问的代码呢?根据最新的JLS,它不应该工作,是吗?@Malcom我看不出有任何矛盾。如果“如果T是引用类型,那么它必须是String”意味着T必须是String或者T作为String处理,则可以有一个参数。我会说,这是美国证券交易委员会