表达式与运算符优先级的从左到右的评估.为什么从左到右的评估似乎胜出了?

Ebo*_*Maw 3 java

考虑以下代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

它评估如下:

x is 2
y is 7
Run Code Online (Sandbox Code Playgroud)

这很有道理,但让我们快速查看运算符优先级表:

在此输入图像描述

据此,应该首先评估后缀运算符.现在,如果我们回到我们的代码,我们将看到x--应该首先评估,但事实并非如此.我不记得什么?

换句话说,如果我们严格遵循运算符优先级表,那么表达式将计算为:

y = ++x * 5 / 3 + --x;

当然,这给了我们一个完全不同的结果y.

Ole*_*.V. 5

你的表达从左到右评估是正确的.这是Java中的一般评估顺序(可能有例外).

我想你已经弄清楚到底发生了什么:

  1. x 从3增加到4并获取其新值4
  2. 5被评估为5
  3. 4*5 = 20
  4. x4 的值用于除法; 除法得到5,x递减到3.
  5. x 在最终加法的值之前进一步递减到2,然后得到7.

除外:只有在可以保证结果相同的情况下,才允许编译器交换步骤.因此我们知道结果只能是7.

尝试将两个概念区分开来:评估顺序和运算符优先级.他们不一样.

优先表告诉你表达式被理解为((++x) * 5 / (x--)) + (--x)(这大部分是好的,因为++(x * 5 / x)-- + --x无论如何都没有意义).

举一个不同的例子:f(x) - g(x) * h(x).该mehtods被称为左到右:f(),然后g()和h()最后一次.优先表仅告诉您乘法在减法之前完成.

编辑:Lew Bloch在评论中质疑,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这打印:

p(): 4
p(): 4
p(): 2
x is 2
y is 7
Run Code Online (Sandbox Code Playgroud)

所以是的,两点x被评估为4.