为什么不遵循运算符优先级?

Edm*_*oid 21 java operators operator-precedence

在这段代码中:

int y = 10;
int z = (++y * (y++ + 5)); 
Run Code Online (Sandbox Code Playgroud)

我的期望

首先y++ + 5将执行,因为最里面的括号的优先级.因此,值y将为11,并且此表达式的值将为15.然后++y * ()将执行.所以12*15 = 180.所以z = 180

我得到了什么

Z = 176

这意味着VM从左到右不遵循运营商优先级.那么我对运算符优先级的理解是错误的吗?

小智 24

表达式(++ y*(y ++ + 5)); 将被放置在这样的堆栈中:

1. [++y]
2. [operation: *]
3. [y++ + 5] // grouped because of the parenthesis
Run Code Online (Sandbox Code Playgroud)

并且它将按此顺序执行,结果

1. 10+1 = [11] // y incremented 
2. [operation: *]
3. 11+5 = [16] // y will only increment after this operation
Run Code Online (Sandbox Code Playgroud)

该表达式被评估为

11 * 16 = 176
Run Code Online (Sandbox Code Playgroud)

  • 如果你正在处理堆栈,[operation:\*]应该在*两个输入后*.它不会影响你在这里所说的重要部分,所以这只是一个小小的狡辩. (11认同)
  • 我觉得这个答案很混乱.如果您正在考虑堆栈计算机,则操作是:计算++ y的副作用和值并将结果推送到堆栈,然后计算y ++的副作用和值并将结果放在堆栈上,然后推送在堆栈上,然后从堆栈中弹出两个东西,添加它们,并在堆栈上推送总和,然后从堆栈中弹出两个东西,将它们相乘,然后将产品放在堆栈上. (6认同)

Mar*_*nik 14

由于最里面的括号的优先级,首先执行y ++ + 5

优先顺序和评估顺序不是一回事.除赋值表达式之外的所有二进制表达式都是从左到右计算的.因此y++,在右侧括号表达式之前进行求值.

  • @EdmDroid没有任何括号,`++ y*y ++ + 5`将被评估为`(++ y*y ++)+ 5` - 这是一个非常不同的表达式. (5认同)
  • 后者不是乘法的右边,它是二进制乘法表达式的右侧*.规则很简单:计算左操作数,然后计算右操作数,然后计算二进制表达式本身.不需要考虑重叠,表达式严格嵌套到树结构中. (2认同)

hac*_*cks 12

括号只描述子表达式如何组合在一起.括号内并不意味着它将首先被评估.相反,java中的规则严格地从左到右评估每个子表达式.

永远记住,评估顺序与运算符优先级关联性完全无关.

Java Oracle文档说:

15.7.评估订单

Java编程语言保证运算符操作数似乎以特定的评估顺序进行评估,即从左到右.

因此,表达式(++y * (y++ + 5))将被评估为

temp1 = ++y = 11
temp2 = y++ + 5 = 11 + 5 = 16 
z = temp1*temp2 = 11*16 = 176  
Run Code Online (Sandbox Code Playgroud)

进一步阅读:Eric Lippert的博客,Precedence vs Associativity vs Order,详细解释了优先级,关联性评估顺序.虽然这个博客解决了但对也同样有效.