考虑下面的例子:
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)进行比较,根据括号所暗示的顺序,应该首先计算右边的值。
为什么第一个表达式的值为假,而第二个表达式的值为真?我希望(x = y)首先被求值,然后它将x与自身(3)进行比较并返回true。
这个问题与Java表达式中子表达式的求值顺序不同,因为x在这里肯定不是“子表达式”。它需要被加载来进行比较,而不是被“评估”。这个问题是java特有的,表达式x == (x = y)与通常为棘手的面试问题而设计的牵强的不切实际的构造不同,它来自一个真实的项目。它应该是比较-替换习惯用法的一行替换
int oldX = x;
x = y;
return oldX == y;
它比x86的CMPXCHG指令更简单,在Java中应该有更短的表达式。
它与操作符优先级以及如何计算操作符有关。
括号'()'优先级更高,具有从左到右的结合性。
等式'=='在这个问题中是下一个,从左到右具有结合律。
赋值'='排在最后,具有从右到左的结合性。
系统使用堆栈计算表达式。表达式从左向右求值。
现在回到最初的问题:
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
首先x(1)将被压入堆栈。
然后inner (x = y)将被计算并推入值为x(3)的堆栈。
现在x(1)将与x(3)进行比较,因此结果为假。
x = 1; // reset
System.out.println((x = y) == x); // true
在这里,
(x = y)将被计算,现在x值变为3,x(3)将被推入堆栈。
现在x(3)的值改变后的等式将被推入堆栈。
现在表达式将被求值,两者将相同,因此结果为真。
它与操作符优先级以及如何计算操作符有关。
括号'()'优先级更高,具有从左到右的结合性。
等式'=='在这个问题中是下一个,从左到右具有结合律。
赋值'='排在最后,具有从右到左的结合性。
系统使用堆栈计算表达式。表达式从左向右求值。
现在回到最初的问题:
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
首先x(1)将被压入堆栈。
然后inner (x = y)将被计算并推入值为x(3)的堆栈。
现在x(1)将与x(3)进行比较,因此结果为假。
x = 1; // reset
System.out.println((x = y) == x); // true
在这里,
(x = y)将被计算,现在x值变为3,x(3)将被推入堆栈。
现在x(3)的值改变后的等式将被推入堆栈。
现在表达式将被求值,两者将相同,因此结果为真。