考虑以下代码:
public class Incrdecr {
static int x = 3;
static int y = ++x * 5 / x-- + --x;
public static void main(String[] args){
System.out.println("x is " + x);
System.out.println("y is " + y);
}
评估如下:
x is 2
y is 7
这很有道理,但让我们快速查看运算符优先级表:
据此,应该首先评估后缀运算符。现在,如果我们回到我们的代码,我们会看到x--
应该先评估,但它不是。我不记得什么?
换句话说,如果我们严格遵循运算符优先级表,那么表达式将计算为:
y = ++x * 5 / 3 + --x;
当然,它为y
提供了完全不同的结果。
答案 0 :(得分:5)
你的表达从左到右评估是正确的。这是Java中的一般评估顺序(可能有例外)。
我认为你已经弄清楚到底发生了什么:
x
从3增加到4,其新值4采用x
,4的值用于划分;除法得到5,x递减到3。x
在最终添加值之前进一步递减到2,然后产生7。除外:只有在可以保证结果相同的情况下,才允许编译器交换步骤。因此我们知道结果只能是7。
尝试将两个概念区分开来:评估顺序和运算符优先级。它们不一样。
优先级表告诉您表达式被理解为((++x) * 5 / (x--)) + (--x)
(这大部分都是好的,因为++(x * 5 / x)-- + --x
无论如何都没有意义。)
举一个不同的例子:f(x) - g(x) * h(x)
。 mehtod从左到右调用:f()
,然后是g()
和h()
。优先表仅告诉您乘法在减法之前完成。
x
在计算过程中的任何时候都会被评估为4。为了测试这个,我从问题中提出了以下程序变体:
public class Incrdecr {
static int x = 3;
static int y = p(++x) * 5 / p(x--) + p(--x);
private static int p(int i) {
System.out.println("p(): " + i);
return i;
}
public static void main(String[] args) {
System.out.println("x is " + x);
System.out.println("y is " + y);
}
}
打印:
p(): 4
p(): 4
p(): 2
x is 2
y is 7
所以是的,在两点x
评估为4。
答案 1 :(得分:2)
{{3}}
后递增/递减遵循运算符的从左到右的关联性。
预增量/减量遵循运算符从右到左的关联性。
也就是说: static int y = ++ x * 5 / x-- + --x;
(x--)存储为x(3)的当前值,然后评估其余值。
++ x被评估为x =(x + 1)强制评估后增量,因为它是一个赋值,因此它变为(3)然后--x被计算为x =(x-1)或2。
这在功能上是等效的: y =(x = x + 1)* 5 / x-- +(x = x-1)(它将在您的Java代码中以这样的方式运行)
得到的等式是:
3 * 5/3 + 2。