为什么 x == (x = y) 与 (x = y) == x 不同?

请考虑以下示例:

class Quirky {
    public static void main(String[] args) {
        int x = 1;
        int y = 3;

        System.out.println(x == (x = y)); // false
        x = 1; // reset
        System.out.println((x = y) == x); // true
     }
}

我不确定Java语言规范中是否有一个项目要求加载变量的先前值,以便与右侧()进行比较,根据括号暗示的顺序,应该首先计算。x = y

为什么第一个表达式的计算结果为 ,而第二个表达式的计算结果为 ?我本来希望首先被评估,然后它会与自身进行比较()并返回。falsetrue(x = y)x3true


这个问题与Java表达式中子表达式的计算顺序不同,因为Java表达式在这里绝对不是“子表达式”。它需要加载以进行比较,而不是“评估”。这个问题是特定于Java的,与通常为棘手的面试问题精心制作的牵强附会的不切实际的构造不同,该表达式来自一个真正的项目。它应该是比较和替换成语的单行替代品xx == (x = y)

int oldX = x;
x = y;
return oldX == y;

它比x86 CMPXCHG指令更简单,值得在Java中使用更短的表达式。


答案 1

==是二元相等运算符

在计算右操作数的任何部分之前,二元运算符的左侧操作数似乎已完全计算完毕。

Java 11 规范>评估顺序>首先评估左侧操作数


答案 2

正如LouisWasserman所说,表达式是从左到右计算的。Java并不关心“evaluate”实际上做了什么,它只关心生成一个(非易失性的,最终的)值来使用。

//the example values
x = 1;
y = 3;

因此,要计算 的第一个输出,请执行以下操作:System.out.println()

x == (x = y)
1 == (x = y)
1 == (x = 3) //assign 3 to x, returns 3
1 == 3
false

并计算第二个:

(x = y) == x
(x = 3) == x //assign 3 to x, returns 3
3 == x
3 == 3
true

请注意,无论 和 的初始值如何,第二个值的计算结果将始终为 true,因为您正在有效地将值的赋值与它所分配到的变量进行比较,并且将按该顺序计算,根据定义始终相同。xya = bb