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
解释是:
- The code does not compile because the assignment operator has the highest order of precedence in this expression.
- 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.
- 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?
我想出了一些理论:
- 表达式求值顺序、运算符优先级和结合性是不同的概念。
- 根据 JLS 15.7.3,表达式计算遵循括号和运算符优先级。
- 所有表达式的计算都是从左到右进行的。
- 运算符优先级决定表达式的分组。
- 结合性只适用于相同的运算符,决定了使用相同运算符的表达式的执行顺序。
- Java 在编译时检查有效表达式,从左到右,尊重括号和运算符优先级。
- 对于带有运算符的表达式,它会根据运算符以不同的方式对 ope运行ds 执行此检查。
有了新知识,我现在将尝试解释第 5 行编译失败的原因:
- Java 开始检查有效表达式,使用表达式计算的顺序,从左到右。
- Java 找到第一个赋值运算符(最左边)。
- 由于赋值运算符“=”具有从右到左的结合性,Java 检查右侧是否有任何其他赋值运算符并开始计算更右的赋值运算符。
- 它找到一个“=”,它检查右侧的任何其他“=”。
- 我找不到其他的“=”,所以它开始评估这个最右边的“=”的操作运行ds。
- 根据 15.26,Java 检查前一个“=”和这个“=”之间的所有内容是否只是一个变量。
- 它找到表达式
250 > 338 ? lion : tiger
,这是一个有效的表达式,但此表达式的计算结果为一个值。
- Java只允许变量在赋值运算符的左边,所以编译失败。
现在我将尝试应用相同的理论来解释这段代码的正确场景:final var statement = 250 > 338 ? lion : (tiger = " is Bigger");
- Java 开始检查有效表达式,使用表达式计算的顺序,从左到右。
- Java 在同一“作用域”中找不到任何其他赋值运算符“=”。
- 根据 15.26,Java 检查此“=”的左操作运行d 是否是一个变量。通过。
- 然后它评估右 ope运行d 是否是一个有效的表达式 returns 一个可分配给左 ope运行d 的值。
考试提供的解释是不是漏掉了球,还是我仍然不明白这段代码为什么没有编译?
- 他们说赋值运算符“=”在这个表达式中以某种方式具有最高的优先级。基于此运算符优先级table、http://www.cs.bilkent.edu.tr/~guvenir/courses/CS101/op_precedence.html,赋值运算符的优先级最低。
- 他们将运算符优先级与求值表达式的顺序互换使用,而不是将这两个概念分开?
你是对的,他们说错了,赋值运算符的优先级是最低。
你错了,他们从来没有在任何地方提到“评估的顺序”(无论如何你已经展示过)。显示的代码在评估顺序很重要的地方没有做任何事情。作业与评估顺序无关。
- The code does not compile because the assignment operator has the highest order of precedence in this expression.
9 > relational
2 ?: ternary
1 = assignment
这意味着要使用括号明确显示优先级,语句变为:
statement = ((250 > 338) ? lion : tiger) = " is Bigger";
- 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)
,“两边”指的是两个赋值运算符
如其所说,“此表达式无效,因为第二个赋值运算符的左侧不是变量”。
- 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") );
我在考试中遇到了这个问题。
试题:以下代码片段的结果是什么?
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
解释是:
- The code does not compile because the assignment operator has the highest order of precedence in this expression.
- 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.
- 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?
我想出了一些理论:
- 表达式求值顺序、运算符优先级和结合性是不同的概念。
- 根据 JLS 15.7.3,表达式计算遵循括号和运算符优先级。
- 所有表达式的计算都是从左到右进行的。
- 运算符优先级决定表达式的分组。
- 结合性只适用于相同的运算符,决定了使用相同运算符的表达式的执行顺序。
- Java 在编译时检查有效表达式,从左到右,尊重括号和运算符优先级。
- 对于带有运算符的表达式,它会根据运算符以不同的方式对 ope运行ds 执行此检查。
有了新知识,我现在将尝试解释第 5 行编译失败的原因:
- Java 开始检查有效表达式,使用表达式计算的顺序,从左到右。
- Java 找到第一个赋值运算符(最左边)。
- 由于赋值运算符“=”具有从右到左的结合性,Java 检查右侧是否有任何其他赋值运算符并开始计算更右的赋值运算符。
- 它找到一个“=”,它检查右侧的任何其他“=”。
- 我找不到其他的“=”,所以它开始评估这个最右边的“=”的操作运行ds。
- 根据 15.26,Java 检查前一个“=”和这个“=”之间的所有内容是否只是一个变量。
- 它找到表达式
250 > 338 ? lion : tiger
,这是一个有效的表达式,但此表达式的计算结果为一个值。 - Java只允许变量在赋值运算符的左边,所以编译失败。
现在我将尝试应用相同的理论来解释这段代码的正确场景:final var statement = 250 > 338 ? lion : (tiger = " is Bigger");
- Java 开始检查有效表达式,使用表达式计算的顺序,从左到右。
- Java 在同一“作用域”中找不到任何其他赋值运算符“=”。
- 根据 15.26,Java 检查此“=”的左操作运行d 是否是一个变量。通过。
- 然后它评估右 ope运行d 是否是一个有效的表达式 returns 一个可分配给左 ope运行d 的值。
考试提供的解释是不是漏掉了球,还是我仍然不明白这段代码为什么没有编译?
- 他们说赋值运算符“=”在这个表达式中以某种方式具有最高的优先级。基于此运算符优先级table、http://www.cs.bilkent.edu.tr/~guvenir/courses/CS101/op_precedence.html,赋值运算符的优先级最低。
- 他们将运算符优先级与求值表达式的顺序互换使用,而不是将这两个概念分开?
你是对的,他们说错了,赋值运算符的优先级是最低。
你错了,他们从来没有在任何地方提到“评估的顺序”(无论如何你已经展示过)。显示的代码在评估顺序很重要的地方没有做任何事情。作业与评估顺序无关。
- The code does not compile because the assignment operator has the highest order of precedence in this expression.
9 > relational
2 ?: ternary
1 = assignment
这意味着要使用括号明确显示优先级,语句变为:
statement = ((250 > 338) ? lion : tiger) = " is Bigger";
- 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)
,“两边”指的是两个赋值运算符
如其所说,“此表达式无效,因为第二个赋值运算符的左侧不是变量”。
- 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") );