简体   繁体   English

Java 运算符优先级指南

[英]Java operator precedence guidelines

Misunderstanding Java operator precedence is a source of frequently asked questions and subtle errors.误解Java 运算符优先级是常见问题和细微错误的根源。 I was intrigued to learn that even the Java Language Specification says, "It is recommended that code not rely crucially on this specification."我很感兴趣地了解到,即使是Java 语言规范也说:“建议代码不要严重依赖此规范。” JLS §15.7 Preferring clear to clever , are there any useful guidelines in this area? JLS §15.7 更喜欢清晰而不是聪明,这方面有什么有用的指导方针吗?

As noted here , this problem should be studied in the context of Evaluation Order , detailed here .正如这里所指出的,这个问题应该在评估顺序的背景下进行研究,这里有详细说明。 Here are a number of resources on the topic:以下是有关该主题的一些资源:

Additions or corrections welcome.欢迎补充或更正。

As far as the "Real World" is concerned, it's probably fair to say:就“现实世界”而言,可以这么说:

  • enough programmers know that multiplication/division take precedence over addition/subtraction, as is mathematically the convention足够多的程序员知道乘法/除法优先于加法/减法,就像数学上的约定一样
  • hardly any programmers can remember any of the other rules of precedence几乎没有程序员能记住任何其他的优先规则

So, apart from the specific case of */ vs +- , I'd really just use brackets to explicitly define the precedence intended.所以,除了*/ vs +-的具体情况,我真的只是使用括号来明确定义预期的优先级。

Another related source of bugs is how rounding errors accumulate.另一个相关的错误来源是舍入误差如何累积。 Not an operator precedence order issue per se, but a source of surprise when you get a different result after rearranging operands in an arithmetically-equivalent way.本身不是运算符优先顺序问题,而是当您以算术等效的方式重新排列操作数后得到不同结果时的惊喜来源。 Here's a sun.com version of David Goldberg's What Every Computer Scientist Should Know About Floating-Point Arithmetic .这是 David Goldberg 的 Sun.com 版本的《每个计算机科学家都应该知道的关于浮点运算的知识》

The quote (from the Java Language Specification §15.7 ) should be read in the context of Evaluation Order .引用(来自Java 语言规范 §15.7 )应该在评估顺序的上下文中阅读。 As discussed here , that section concerns evaluation order , which is not related to operator precedence (or associativity ).正如这里所讨论的,该部分涉及评估顺序,它与运算符优先级(或关联性)无关。

Precedence and associativity influence the structure of the expression tree (ie which operators act on which operands), while "evaluation order" merely influences the order in which the expression tree is traversed when the expression is evaluated.优先级和关联性影响表达式树的结构(即,哪些运算符作用于哪些操作数),而“求值顺序”仅影响表达式树在求值时遍历的顺序。 Evaluation order (or "traversal order") does not have any effect unless some sub-expressions have side-effects that affect the result (or side-effects) of other sub-expressions.除非某些子表达式具有影响其他子表达式的结果(或副作用)的副作用,否则评估顺序(或“遍历顺序”)不会产生任何影响。

For example, if x==1 initially, the expression ++x/++x would evaluate as 2/3 (which evaluates to 0) since Java has left-to-right evaluation order.例如,如果最初 x==1,则表达式++x/++x将计算为 2/3(计算结果为 0),因为 Java 具有从左到右的计算顺序。 Had evaluation order in Java been right-to-left, x would have been incremented twice before the numerator is evaluated, and the expression would have evaluated as 3/2 (which evaluates to 1).如果 Java 中的计算顺序是从右到左,x 在计算分子之前将增加两次,并且表达式将计算为 3/2(计算结果为 1)。 Had evaluation order been undefined, the expression could have evaluated to either of these results.如果未定义评估顺序,则表达式可能已评估为这些结果中的任何一个。

The quote in question, together with its context, ...有问题的报价,连同它的上下文,......

The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right. Java 编程语言保证运算符的操作数看起来是以特定的评估顺序进行评估的,即从左到右。

It is recommended that code not rely crucially on this specification.建议代码不要严重依赖本规范。 Code is usually clearer when each expression contains at most one side effect, as its outermost operation当每个表达式最多包含一个副作用时,代码通常会更清晰,因为它的最外层操作

...discourages the reader from depending on the left-to-rightness of Java's evaluation order (as in the example above). ...阻止读者依赖 Java评估顺序的从左到右(如上例所示)。 It does not encourage unnecessary parentheses.它不鼓励不必要的括号。

Edit: Resource: Java operator precedence table that also serves as an index into sections of the JLS containing the syntactic grammar from which each precedence level is inferred.编辑:资源: Java 运算符优先级表,它还用作 JLS 部分的索引,其中包含推断每个优先级的句法语法。

Also, don't forget the logical && and ||另外,不要忘记逻辑 && 和 || are shortcut operators, avoid something like:是快捷操作符,避免类似:

sideeffect1() || sideeffect2()

If sideeffect1() is evaluating to true, sideeffect2() isn't going to be executed.如果 sideeffect1() 评估为真,则 sideeffect2() 不会被执行。 The same goes for && and false. && 和 false 也是如此。 This is not entirely related to precendence, but in these extreme cases the assiociativity can also be an important aspect that normally is really irrelevant (at least as far as i am concerned)这与优先级并不完全相关,但在这些极端情况下,关联性也可能是一个重要的方面,通常情况下是无关紧要的(至少就我而言)

The JLS does not give an explicit operator precedence table; JLS没有给出明确的运算符优先级表; it is implied when the JLS describes various operators.JLS描述各种运算符时,它是隐含的。 For example, the grammar for ShiftExpression is this:例如, ShiftExpression的语法是这样的:

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

This means that additive operators ( + and - ) have a higher precedence than the left-associative shift operators ( << , >> and >>> ).这意味着加法运算符( +- )比左结合移位运算符( <<>>>>> )具有更高的优先级。

It seems to me that the truth of this is that 'most programmers' think 'most other programmers' don't know or can't remember operator precedence, so they indulge in what is indulgently called 'defensive programming' by 'inserting the missing parentheses', just to 'clarify' that.在我看来,事实是“大多数程序员”认为“大多数其他程序员”不知道或不记得运算符优先级,所以他们沉迷于所谓的“防御性编程”,即“插入缺失的”括号”,只是为了“澄清”这一点。 Whether remembering this third-grade stuff is a real problem is another question.记住这些三年级的东西是否是一个真正的问题是另一个问题。 It just as arguable that all this is a complete waste of time and if anything makes things worse.同样可以说,所有这些完全是浪费时间,如果有任何事情会使事情变得更糟。 My own view is that redundant syntax is to be avoided wherever possible, and that computer programmers should know the language they are programming in, and also perhaps raise their expectations of their colleagues.我自己的观点是,应尽可能避免冗余语法,计算机程序员应该了解他们正在编程的语言,并可能提高他们对同事的期望。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM