5
public static void main(String[] args) {
    int A=5;
    int B=2;

    A *= B*= A *= B ;

    System.out.println(A);
    System.out.println(B);
}

当我在纸上计算这个问题时,我发现了A=200 B=20,但是当我把它写下来到 Eclipse 时,它​​显示A=100 B=20

你能像在纸上解决一样解释解决方案吗?

我试图在 Eclipse 中自己解决。

我们如何解决它?

4

2 回答 2

6

A=5,B=2

A变为A * B * A * B,即 100, B变为B * A * B,即 20。


更详细地说:

A *= B *= A *= B

A = A * (B = B * (A = A * B)) 

这解决了

A = 5 * (B = 2 * (A = 5 * 2))

意思是

A = 5 * (B = 2 * (A = 10)) // set A to 10
A = 5 * (B = 2 * 10)
A = 5 * (B = 20) // set B to 20
A = 5 * 20
A = 100 // set A to 100
于 2019-08-22T22:33:43.590 回答
5

这与在运算符顺序(优先级)之前进行的操作数评估有关。

在执行运算符之前,计算操作数,在 Java 中总是以从左到右的顺序进行。

最左边A的被评估为5,然后最左边B的是2,然后第二个A5,第二个B也是2。保存这些值以供以后计算。

JLS第15.26.2 节处理评估复合赋值运算符的过程。

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

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

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

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

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

(粗体强调我的)

然后执行运算符,*=具有右关联性。这意味着操作从右到左进行。最右边A *= B的被执行,分配10A. 中间B *= A被执行,分配20B. 但是,当最左边A *= B的执行时,保存的值A仍然存在 - 5。乘以 时20100分配给A

A *= B*= A *= B;  // A is now 100

如果我们将其分解为 3 个语句,那么您将得到预期的200,因为A将作为最后一个语句的一部分再次评估为10,而不是5,因为保存的值为Anow 10

A *= B;
B *= A;
A *= B;  // A is now 200
于 2019-08-22T22:48:06.143 回答