【问题标题】:Order of operations for compound assignment operators in JavaJava中复合赋值运算符的运算顺序
【发布时间】:2015-11-17 15:34:50
【问题描述】:

我最近在模拟考试中遇到了以下问题,对于为什么给出的答案根据操作顺序是 25, 25 以及我可能遗漏的内容有点迷茫详细说明原因的规范。

public class Test {

    public static void main(String[] args) {
        int k = 1;
        int[] a = {1};
        k += (k = 4) * (k + 2);
        a[0] += (a[0] = 4) * (a[0] + 2);
        System.out.println(k + " , " + a[0]);
    }
}

仅查看上面的第 6 行,我替换了适当的值,并得到以下结果:

k = k + (k = 4) * (k + 2);

我首先评估括号,这表明 k 首先被赋值为 4,然后被添加到数字 2,得到总数 6。这就是我的解释:

k = k + 4 * 6;

现在这是令人困惑的地方。根据操作顺序,我得到以下内容,考虑到前面的表达式,这将是正确的:

k = k + 24;

在我看来,此时 k 应该是 4,因为那是新的赋值,但答案实际上是 25,而不是 28。显然复合运算符有一些优先顺序,我不是理解,或者我的替换原则不正确。

【问题讨论】:

  • 这就是为什么您应该始终使用final 变量的原因,最左侧的k 不会改变,因为您在右侧进行了更改。你认为你用这种令人费解的混淆逻辑完成了什么?
  • 问题的第一句话:“我最近在模拟考试中遇到了以下内容......”。我永远不会故意编写这些垃圾代码。
  • 告诉提出这类问题的人,这些问题既愚蠢又不切实际
  • 括号定义优先级,而不是执行顺序。例如,在n = 1; m = n + (n = 2); 中,m 将等于 3,而不是 4。即仅仅因为(n = 2) 在括号中并不意味着您首先评估它。

标签: java


【解决方案1】:

在这个答案中,我只会考虑k 的情况,数组也是如此。

int k = 1;
k += (k = 4) * (k + 2);
// k += (k = 4) * (k + 2)
// 1 += (k = 4) * (k + 2)
// 1 +=    4    * (k + 2) with k = 4
// 1 +=    4    *   6     with k = 4
// k = 25

这里的技巧:

  • k += 在进行计算之前捕获 k 的值。 += 称为 compound assignment operator。引用 JLS 的相关部分:

    保存左侧操作数的值,然后计算右侧操作数。

  • k = 4 返回分配的值,所以 4。

【讨论】:

  • 我认为键的一部分“......保存左侧操作数的值,然后评估右侧操作数。”是这个评估发生在右手的任何其他操作顺序之前。这是一个“安全”的假设吗?我问的唯一原因是因为学习认证的很大一部分是能够正确应用规则,而这其中的规则可能是几个规则的子集。
  • @BrianReindel 是的,保证k 的值在评估右侧之前会被保存。无论您对右侧的 k 做什么,它都将始终保持其先前的值,在本例中为 1。
猜你喜欢
  • 2011-11-16
  • 1970-01-01
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 2014-04-17
  • 1970-01-01
相关资源
最近更新 更多