为什么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
)进行比较,该变量应按照方括号内的顺序进行计算。
为什么第一个表达式求值false
,而第二个表达式求值true
?我本来希望(x =
y)先被评估,然后再x
与自身(3
)比较并返回true
。
这个问题与Java表达式中子表达式的求值顺序不同,因为x
这里绝对不是“子表达式”。需要
它以进行比较,而不是对其进行“评估”。这个问题是特定于Java的x == (x =
y),与通常为棘手的面试问题设计的牵强的不切实际的构造不同,该表达式来自一个真实的项目。它本来是用于替换和替换成语的单行替换
int oldX = x;x = y;
return oldX == y;
它比x86 CMPXCHG指令还要简单,因此值得在Java中使用较短的表达式。
回答:
首先应按照括号中的顺序计算
不会。圆括号对计算或评估顺序有任何(一般)影响,这是一个普遍的误解。它们仅将表达式的各部分强制转换为特定的树,将正确的操作数绑定到作业的正确操作。
(而且,如果您不使用它们,则此信息来自运算符的“优先级”和关联性,这是语言的语法树定义方式的结果。实际上,这仍然是您使用语言时的工作方式使用括号,但我们简化并说我们当时不依赖任何优先规则。)
一旦完成(即,将您的代码解析为程序),仍然需要对那些操作数进行求值,并且有分别的操作规则:所述规则(如安德鲁向我们展示的那样)指出每个操作的LHS首先用Java评估。
请注意,并非所有语言都如此。例如,在C
++中,除非您使用短路运算符(如&&
或)||
,否则操作数的求值顺序通常是不确定的,并且您不应以任何方式依赖它。
教师需要停止使用具有误导性的短语来解释操作员优先级,例如“这使得添加首先发生”。给定一个表达式x * y + z
,正确的解释是“运算符优先级使在x *
y和之间进行加法z
,而不是在y
和之间进行加法,而z
没有提及任何”顺序”。
以上是 为什么x ==(x = y)与(x = y)== x不同? 的全部内容, 来源链接: utcz.com/qa/400502.html