Question

Misunderstanding Java operator precedence is a source of frequently asked questions and subtle errors. I was intrigued to learn that even the Java Language Specification says, "It is recommended that code not rely crucially on this specification." JLS §15.7 Preferring clear to clever, are there any useful guidelines in this area?

Here are a number of resources on the topic:

Additions or corrections welcome.

Was it helpful?

Solution

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.

OTHER TIPS

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.

The quote (from the Java Language Specification §15.7) should be read in the context of Evaluation Order. 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 (i.e. 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. 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). 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.

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). 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.

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. The same goes for && and 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; it is implied when the JLS describes various operators. For example, the grammar for ShiftExpression is this:

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top