这个Java程序中运算符优先的逻辑有什么问题?

这个Java程序中运算符优先的逻辑有什么问题?,java,operator-keyword,operator-precedence,Java,Operator Keyword,Operator Precedence,根据运算符优先级,后缀运算符的优先级高于乘法运算符。括号内的操作数具有更高的优先级 首先评估它们:i*(i+++i) 现在,括号内是10+11:i*(21) i的当前值是11 其次,根据下一个优先级计算乘法运算符,它是否应该是11*21=231 虽然我知道答案是210,但为什么我上面解释的逻辑是错误的呢?将其分成以下几部分 class Hello { public static void main(String args[]) { int i = 10;

根据运算符优先级,后缀运算符的优先级高于乘法运算符。括号内的操作数具有更高的优先级

首先评估它们:i*(i+++i) 现在,括号内是10+11:i*(21)

i的当前值是11

其次,根据下一个优先级计算乘法运算符,它是否应该是11*21=231


虽然我知道答案是210,但为什么我上面解释的逻辑是错误的呢?

将其分成以下几部分

class Hello {
    public static void main(String args[]) {
        int i = 10;
        i *= i++ + i;
        System.out.println(i);
    }
}
现在,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
那么,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
那么,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
那么,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
那么,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
如您所见,首先加载“i”的值,然后完成剩余的计算,而不是相反

编辑: 在这两者之间的某个地方,i的值也被设置为11,因此在步骤4中数字“11”,但在这之后,它在最后被覆盖,所以这个值不再重要

交换计算将产生您想要的结果:

i = 210;

把它分成以下几部分

class Hello {
    public static void main(String args[]) {
        int i = 10;
        i *= i++ + i;
        System.out.println(i);
    }
}
现在,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
那么,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
那么,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
那么,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
那么,你有:

i = i * (i++ + i);
i = 10 * (i++ + i);
i = 10 * (10 + i);
i = 10 * (10 + 11);
i = 10 * (21);
如您所见,首先加载“i”的值,然后完成剩余的计算,而不是相反

编辑: 在这两者之间的某个地方,i的值也被设置为11,因此在步骤4中数字“11”,但在这之后,它在最后被覆盖,所以这个值不再重要

交换计算将产生您想要的结果:

i = 210;

仅仅因为运算符必须按特定顺序应用,并不意味着必须首先计算最高优先级运算符的直接操作数

事实上,这里适用的规则是:

Java编程语言保证运算符的操作数按特定的求值顺序求值,即从左到右。在计算右操作数的任何部分之前,二元运算符的左操作数似乎已被完全计算。2011年7月23日


除非遵循一条简单的规则,否则这可能会非常混乱:不要嵌入副作用会影响操作数计算的子表达式,因为它会使代码无法读取。

仅仅因为必须按特定顺序应用运算符,并不意味着必须首先计算最高优先级运算符的直接操作数

事实上,这里适用的规则是:

Java编程语言保证运算符的操作数按特定的求值顺序求值,即从左到右。在计算右操作数的任何部分之前,二元运算符的左操作数似乎已被完全计算。2011年7月23日


除非遵循一条简单的规则,否则这可能会非常混乱:不要嵌入副作用会影响操作数的子表达式,因为它会使代码无法读取。

首先要注意的是,您不是在进行简单的乘法运算,而是在使用
复合赋值运算符,这是一个运算符,封装对变量执行操作,然后将结果分配给原始变量

从(如
*=
):

  • 首先,对左侧操作数求值以生成变量。如果 此求值突然完成,然后赋值表达式 出于同样的原因突然完成;右操作数不正确 已计算,但未发生赋值

  • 否则,保存左侧操作数的值,然后 计算右侧操作数。如果此评估完成 突然,则赋值表达式为 相同的原因,并且没有分配发生

  • 否则,左侧变量的保存值和右侧操作数的值将用于执行复合赋值运算符指示的二进制运算。如果此操作突然完成,则赋值表达式出于相同的原因突然完成,并且不会发生赋值
突出显示的文本保证在乘法的左侧使用
i
的原始值,即10。(右侧的计算结果为21,因为您已经正确推导了。)

另一个可能更重要的教训是,运算符优先级与求值顺序不同。优先级仅用于将表达式解析为表达式树,但运算符的计算始终是从左到右,从外到内

在您的示例中,表达式树大致如下所示(请注意,最低优先级运算符如何结束于树的根):

…现在从上到下,从左到右进行评估,如下所示:

    *=
   /  \
  i    +
      / \
     i++ i

这里首先要注意的是,您不是在做简单的乘法,而是在使用一个
复合赋值运算符
,这是一个对变量执行操作,然后将结果赋值给原始变量的运算符

从(如
*=
):

  • 首先,对左侧操作数求值以生成变量。如果 此求值突然完成,然后赋值表达式 出于同样的原因突然完成;右操作数不正确 已计算,但未发生赋值

  • 否则,保存左侧操作数的值,然后 计算右侧操作数。如果此评估完成 突然,则赋值表达式为 相同的原因,并且没有分配发生

  • 否则,左侧变量的保存值和右侧operan的值