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



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

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

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

正确答案是

F。由于第5行,代码将无法编译

解释如下:

  1. 由于赋值运算符在此表达式中具有最高优先级,因此代码不会编译
  2. 三元运算符的两边必须具有相同的类型。此表达式无效,因为第二个赋值的左侧运算符不是一个变量,所以答案是选项F
  3. 请注意,如果问题在表达式周围添加了明确的括号(Tiger="is Bigger"),选项E将具有正确的输出

当我自己运行代码时,我得到了一个编译错误:

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问题:

Java中的评估顺序规则是什么?

如果括号的优先级更高,那么为什么要先求解增量运算符?

我提出了一些理论:

  1. 表达式求值顺序、运算符优先级和关联性是不同的概念
  2. 根据JLS 15.7.3,表达式求值尊重括号和运算符优先级
  3. 所有表达式求值都是从左到右进行的
  4. 运算符优先级决定表达式的分组
  5. 关联性仅适用于同一运算符,并确定使用同一运算符的表达式的执行顺序
  6. Java在编译时从左到右根据括号和运算符的优先级检查有效表达式
  7. 对于带有运算符的表达式,它根据运算符以不同的方式对操作数执行此检查

有了新知识,我现在将尝试解释为什么第5行编译失败:

  1. Java开始使用表达式求值的顺序从左到右检查有效表达式
  2. Java找到第一个赋值运算符(最左边)
  3. 由于赋值运算符"="具有从右到左的关联性,Java检查右侧是否有其他赋值运算符,并开始计算更右侧的赋值运算符
  4. 它发现一个"=&";,它检查任何其它的"="右侧
  5. 我找不到其他"=&";,因此它开始计算这个最右边的"0"的操作数=&">
  6. 根据15.26="而这个"="只是一个变量
  7. 它查找表达式250 > 338 ? lion : tiger,这是一个有效的表达式,但此表达式的计算结果为一个值
  8. Java只允许变量位于赋值运算符的左侧,因此无法编译

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

  1. Java开始使用表达式求值的顺序从左到右检查有效表达式
  2. Java没有发现任何其它赋值运算符"="在相同的";"范围">
  3. 根据15.26,Java检查这个"="是一个变量。通过
  4. 然后,它评估右操作数是否是返回可赋值给左操作数的值的有效表达式

考试提供的解释是否失败了,或者我仍然不明白这段代码是如何没有编译的?

  1. 他们指出赋值运算符"="不知何故,在这个表达式中具有最高的优先级。基于该运算符优先级表,http://www.cs.bilkent.edu.tr/~guvenir/course/CS101/op_predecance.html,赋值运算符的优先级最低
  2. 他们将运算符优先级与求值表达式的顺序互换使用,而不是将这两个概念分开

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

你错了,他们从来没有提到";评估的顺序";任何地方(不管怎样,你已经展示了)。显示的代码在评估顺序很重要的情况下不会执行任何操作。任务与评估顺序无关。



  1. 由于赋值运算符在此表达式中具有最高优先级,因此代码不会编译

操作员优先级显示:

9   >   relational
2   ?:  ternary
1   =   assignment

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

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

  1. 三元运算符的两边必须具有相同的类型。这个表达式无效,因为第二个赋值运算符的左侧不是变量,所以答案是选项F

三元运算符是((250 > 338) ? lion : tiger);两侧";请参阅两个赋值运算符。

正如它所说;这个表达式是无效的,因为第二个赋值运算符的左侧不是变量";。


  1. 注意,如果问题在表达式周围添加了显式括号(Tiger="is Bigger"),选项E将具有正确的输出

您自己已经确认了。

为了使用括号显式显示优先级,语句变为:

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

最新更新