22

误解Java 运算符优先级是常见问题和细微错误的根源。我很感兴趣地了解到,甚至Java 语言规范都说:“建议代码不要严重依赖该规范。” JLS §15.7 更喜欢清晰而不是聪明,这方面有什么有用的指导方针吗?

以下是有关该主题的一些资源:

欢迎补充或更正。

4

6 回答 6

20

就“现实世界”而言,可以这么说:

  • 足够多的程序员知道乘法/除法优先于加法/减法,就像数学上的约定一样
  • 几乎没有程序员能记住任何其他的优先规则

所以,除了*/vs的具体情况+-,我真的只是使用方括号来明确定义预期的优先级。

于 2010-01-26T05:57:20.743 回答
5

另一个相关的错误来源是舍入误差如何累积。本身不是运算符优先顺序问题,而是当您以算术等效的方式重新排列操作数后得到不同结果时的惊喜来源。这是 David Goldberg 的 Sun.com 版本的《每个计算机科学家都应该知道的关于浮点运算的知识》

于 2010-02-15T06:22:44.713 回答
4

引用(来自Java 语言规范 §15.7)应该在评估顺序的上下文中阅读。正如这里所讨论的,该部分涉及评估顺序,它与运算符优先级(或关联性)无关。

优先级和关联性影响表达式树的结构(即,哪些运算符作用于哪些操作数),而“求值顺序”仅影响表达式树在求值时遍历的顺序。除非某些子表达式具有影响其他子表达式的结果(或副作用)的副作用,否则评估顺序(或“遍历顺序”)不会产生任何影响。

例如,如果最初 x==1,则表达式的++x/++x计算结果为 2/3(计算结果为 0),因为 Java 具有从左到右的计算顺序。如果 Java 中的计算顺序是从右到左,x 在计算分子之前将增加两次,并且表达式将计算为 3/2(计算结果为 1)。如果未定义评估顺序,则表达式可能已评估为这些结果中的任何一个。

有问题的报价,连同它的上下文,......

Java 编程语言保证运算符的操作数看起来是以特定的评估顺序进行评估的,即从左到右。

建议代码不要严重依赖本规范。当每个表达式最多包含一个副作用时,代码通常会更清晰,因为它的最外层操作

...阻止读者依赖 Java评估顺序的从左到右(如上例所示)。它不鼓励不必要的括号。

编辑:资源:Java 运算符优先级表,它还用作 JLS 部分的索引,其中包含推断每个优先级的句法语法。

于 2012-11-12T23:21:44.243 回答
2

另外,不要忘记逻辑 && 和 || 是快捷操作符,避免类似:

sideeffect1() || sideeffect2()

如果 sideeffect1() 评估为真,则 sideeffect2() 不会被执行。&& 和 false 也是如此。这与优先级并不完全相关,但在这些极端情况下,关联性可能是一个重要的方面,通常是无关紧要的(至少就我而言)

于 2012-11-24T16:20:50.363 回答
2

JLS没有给出明确的运算符优先级表;当JLS描述各种运算符时,它是隐含的。例如, for 的语法ShiftExpression是这样的:

ShiftExpression:
    AdditiveExpression
    ShiftExpression << AdditiveExpression
    ShiftExpression >> AdditiveExpression
    ShiftExpression >>> AdditiveExpression

这意味着加法运算符 (+和) 比左结合移位运算符 ( ,和-) 具有更高的优先级。<<>>>>>

于 2013-01-01T01:24:49.807 回答
1

在我看来,事实是“大多数程序员”认为“大多数其他程序员”不知道或不记得运算符优先级,所以他们沉迷于所谓的“防御性编程”,即“插入缺失的”括号”,只是为了“澄清”这一点。记住这些三年级的东西是否是一个真正的问题是另一个问题。同样可以说,所有这些完全是浪费时间,如果有任何事情会使事情变得更糟。我自己的观点是,应尽可能避免冗余语法,计算机程序员应该了解他们正在编程的语言,并可能提高他们对同事的期望。

于 2012-10-13T08:10:57.107 回答