Java 表达式顺序、运算符优先级和结合性之间的差异

Differences between Java order of expression, operator precedence and associativity

我在考试中遇到了这个问题。

试题:以下代码片段的结果是什么?

3: var tiger = "Tiger";
4: var lion = "Lion";
5: final var statement = 250 > 338 ? lion : tiger = " is Bigger";
6: System.out.println(statement);

正确答案是

F. The code will not compile because of line 5

解释是:

  1. The code does not compile because the assignment operator has the highest order of precedence in this expression.
  2. Both sides of the ternary operator must have the same type. This expression is invalid, as the left side of the second assignment operator is not a variable, so the answer is option F.
  3. Note that if the question had added explicit parentheses around the expression (Tiger = " is Bigger"), option E would have the correct output.

当我运行自己编写代码时,出现编译错误:

test.java:11: error: unexpected type
final var statement = 250 > 338 ? lion : tiger = " is Bigger";
                                ^
  required: variable
  found:    value
1 error
error: compilation failed

征求第二意见后,阅读 JLS 部分 15,以及其他 SO 问题:

What are the rules for evaluation order in Java?

我想出了一些理论:

  1. 表达式求值顺序、运算符优先级和结合性是不同的概念。
  2. 根据 JLS 15.7.3,表达式计算遵循括号和运算符优先级。
  3. 所有表达式的计算都是从左到右进行的。
  4. 运算符优先级决定表达式的分组。
  5. 结合性只适用于相同的运算符,决定了使用相同运算符的表达式的执行顺序。
  6. Java 在编译时检查有效表达式,从左到右,尊重括号和运算符优先级。
  7. 对于带有运算符的表达式,它会根据运算符以不同的方式对 ope运行ds 执行此检查。

有了新知识,我现在将尝试解释第 5 行编译失败的原因:

  1. Java 开始检查有效表达式,使用表达式计算的顺序,从左到右。
  2. Java 找到第一个赋值运算符(最左边)。
  3. 由于赋值运算符“=”具有从右到左的结合性,Java 检查右侧是否有任何其他赋值运算符并开始计算更右的赋值运算符。
  4. 它找到一个“=”,它检查右侧的任何其他“=”。
  5. 我找不到其他的“=”,所以它开始评估这个最右边的“=”的操作运行ds。
  6. 根据 15.26,Java 检查前一个“=”和这个“=”之间的所有内容是否只是一个变量。
  7. 它找到表达式 250 > 338 ? lion : tiger,这是一个有效的表达式,但此表达式的计算结果为一个值。
  8. Java只允许变量在赋值运算符的左边,所以编译失败。

现在我将尝试应用相同的理论来解释这段代码的正确场景:final var statement = 250 > 338 ? lion : (tiger = " is Bigger");

  1. Java 开始检查有效表达式,使用表达式计算的顺序,从左到右。
  2. Java 在同一“作用域”中找不到任何其他赋值运算符“=”。
  3. 根据 15.26,Java 检查此“=”的左操作运行d 是否是一个变量。通过。
  4. 然后它评估右 ope运行d 是否是一个有效的表达式 returns 一个可分配给左 ope运行d 的值。

考试提供的解释是不是漏掉了球,还是我仍然不明白这段代码为什么没有编译?

  1. 他们说赋值运算符“=”在这个表达式中以某种方式具有最高的优先级。基于此运算符优先级table、http://www.cs.bilkent.edu.tr/~guvenir/courses/CS101/op_precedence.html,赋值运算符的优先级最低。
  2. 他们将运算符优先级与求值表达式的顺序互换使用,而不是将这两个概念分开?

你是对的,他们说错了,赋值运算符的优先级是最低

你错了,他们从来没有在任何地方提到“评估的顺序”(无论如何你已经展示过)。显示的代码在评估顺序很重要的地方没有做任何事情。作业与评估顺序无关。



  1. The code does not compile because the assignment operator has the highest order of precedence in this expression.

Operator precedence 显示:

9   >   relational
2   ?:  ternary
1   =   assignment

这意味着要使用括号明确显示优先级,语句变为:

statement = ((250 > 338) ? lion : tiger) = " is Bigger";

  1. Both sides of the ternary operator must have the same type. This expression is invalid, as the left side of the second assignment operator is not a variable, so the answer is option F.

三元运算符为((250 > 338) ? lion : tiger),“两边”指的是两个赋值运算符

如其所说,“此表达式无效,因为第二个赋值运算符的左侧不是变量”。


  1. Note that if the question had added explicit parentheses around the expression (Tiger = " is Bigger"), option E would have the correct output.

你自己已经确认了。

要使用括号明确显示优先级,语句变为:

statement = ( (250 > 338) ? lion : (tiger = " is Bigger") );