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
,但是当我写下来使其日蚀时,却显示了A=100 B=20
您能在纸上解释解决方案吗?
我试图独自在Eclipse中解决问题。
我们如何解决?
答案 0 :(得分:5)
从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
答案 1 :(得分:4)
这与运算符在运算符顺序(优先级)之前发生的求值有关。
在执行运算符之前,将对操作数进行求值,这在Java中始终按从左到右的顺序进行。
最左边的A
被评估为5
,然后最左边的B
是2
,然后第二个A
是5
并且第二个B
也是2
。这些值将保存以供以后计算。
JLS, Section 15.26.2处理评估复合赋值运算符的过程。
如果左侧操作数表达式不是数组访问表达式,则:
首先,对左侧操作数求值以产生一个变量。如果该评估突然完成,则赋值表达式由于相同的原因而突然完成;右边的操作数不会被评估,也不会发生赋值。
否则,将保存左手操作数的值,然后评估右手操作数。如果此评估突然完成,则赋值表达式由于相同的原因突然完成,并且不会发生赋值。
否则,左侧变量的 saved 值和右侧操作数的值将用于执行复合赋值运算符指示的二进制运算。如果此操作突然完成,则赋值表达式由于相同的原因而突然完成,并且不会发生赋值。
否则,将二进制运算的结果转换为左侧变量的类型,然后将值集转换(第5.1.13节)转换为适当的标准值集(而不是扩展指数值)设置),然后将转换结果存储到变量中。
(加粗强调)
然后执行操作符,其中*=
具有右关联性。这意味着操作从右向左进行。执行最右边的A *= B
,将10
分配给A
。执行中间的B *= A
,将20
分配给B
。但是,执行最左边的A *= B
时,A
的 saved 值仍然存在-5
。将20
乘以100
会分配给A
。
A *= B*= A *= B; // A is now 100
如果我们将其分解为3条语句,则您将获得预期的200
,因为A
将作为最后一条语句的一部分再次被评估为10
,而不是{{ 1}},因为5
的保存值现在为A
。
10