0

我对以下代码的结果有点困惑:

    int x = 1;
    x -= ((x += 1) << 1);
    System.out.println(x);

它会打印出来-3,但我希望它会打印出来-2,因为在我的脑海中,计算应该是这样的:

| Opearation | Returned | x |
+------------+----------+---+
| int x = 1; |     -    | 1 |
+------------+----------+---+
| (x += 1)   |     2    | 2 |
+------------+----------+---+
| (2 << 1)   |     4    | 2 |
+------------+----------+---+
| x -= 4;    |     -    |-2 |

我在这里想念什么?有人可以向我解释发生了什么吗?

谢谢!

4

4 回答 4

3

JLS 15.26.2 如下所述,https: //docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.26.2

如果左侧操作数表达式不是数组访问表达式,则:

首先,评估左侧操作数以产生变量。如果这个求值突然完成,那么赋值表达式也会因为同样的原因而突然完成;不计算右侧操作数,也不发生赋值。

否则,将保存左侧操作数的值,然后计算右侧操作数。如果这个求值突然完成,那么赋值表达式也会因为同样的原因而突然完成并且没有赋值发生。

否则,左侧变量的保存值和右侧操作数的值用于执行复合赋值运算符指示的二元运算。如果此操作突然完成,则赋值表达式出于同样的原因突然完成并且不发生赋值。

否则,二元运算的结果被转换为左侧变量的类型,经过值集转换(第 5.1.13 节)到适当的标准值集(不是扩展指数值集),结果转换的存储到变量中。

所以 的原始值x,即 1,被保存,然后 RHS 被评估。因此是-3.

于 2017-10-29T21:45:50.833 回答
0

x (=1) 的值在处理子表达式 (x+=1) 之前填充在表达式的 RHS 上,因此最左边的 x 在 x+=1 中处理之前被替换为 1 方式,结果为 2。因此它将会 ...

x = 1 - ((x=1+1) << 1)
x = 1 - ((x=2) << 1)
x = 1 - (2 << 1)
x = 1 - 4
x = -3

这里 x=2 结果为 2,因为赋值运算符返回与分配给变量的值相同的值。

于 2017-10-29T21:46:45.207 回答
0

与其他一些语言(看着你,C++)不同,Java 语言规范保证表达式操作数是从左到右计算的

Java 编程语言保证运算符的操作数看起来是以特定的评估顺序进行评估的,即从左到右。

让我们展开您的复合语句:

x -= ((x += 1) << 1);
x = x - ((x = x + 1) << 1);
    ^

首先x计算带有箭头的 ,这意味着表达式中稍后发生的赋值不会影响值(在这种情况下,JVM 堆栈1上已经有 a )。其余的评估按照您的预期进行,但最终的操作是1 - 4 = -3.

请注意,在上述声明之后,JLS 还包含一个绝对适用于此处的注释:

建议代码不要严重依赖本规范。当每个表达式最多包含一个副作用时,代码通常会更清晰,作为其最外层的操作,并且当代码不完全依赖于表达式的从左到右求值的结果出现的异常时。

于 2017-10-29T21:47:07.077 回答
-1
x -= ((x += 1) << 1);
x = x - ((x += 1) << 1);
  = 1 - ((1 + 1) << 1);
  = 1 - (2 << 1)
  = 1 - 4
  = -3
于 2017-10-29T21:38:46.310 回答