How does operator precedence differ from operand evaluation order in Java? Use an expression with side effects to illustrate.
answer
- Precedence = structure (parse tree)
- Evaluation order = timeline (left to right)
- Higher precedence != evaluated first
- Java pins left-to-right; C/C++ does not
- Side effects expose the difference
basics
~20 sPrecedence decides how operators group their operands; evaluation order decides which operand runs first in time. In Java operands always run left to right, no matter the precedence, so a higher-precedence operator can still have its operands computed later.
solid answer
~50 sThese are two independent rules that people conflate. **Precedence (and associativity)** is a purely structural rule: it determines the parse tree — which operator binds which operands, e.g. `*` groups before `+`. **Evaluation order** is a runtime rule: Java guarantees that, within an expression, the operands are evaluated **strictly left to right**, and each operand is fully evaluated before the next. Consider `int x = add() + mul() * 1;` where `add` and `mul` have side effects: even though `*` has higher precedence and so `mul() * 1` is *grouped* first, `add()` is still *called* first because it appears to the left. So precedence shapes the tree; left-to-right shapes the timeline. This distinction is why expressions like `i = i++ + ++i` are well-defined in Java (unlike C/C++) — the language pins the evaluation order, so the result is deterministic even when undefined elsewhere.
code
java · 9 linesstatic int log(int v, String tag) {
System.out.println(tag);
return v;
}
// Precedence groups as log(2) + (log(3) * log(4)) -> value 14
// Evaluation order prints A, B, C (strict left to right)
int x = log(2, "A") + log(3, "B") * log(4, "C");
System.out.println(x); // 14go deeper
May not need this distinction yet, but should at least know operands run left to right.
States that precedence is about grouping and Java evaluates left to right, and can trace a simple side-effecting expression.
Cleanly separates parse-tree structure from runtime timeline, cites Java's strict left-to-right guarantee, and explains i = i++ + ++i and short-circuiting.
Contrasts Java's defined ordering with C/C++ undefined behavior, flags order-dependent expressions as a maintainability/portability hazard, and sets conventions to keep side effects out of compound expressions.
## Two separate questions Given an expression, there are two distinct questions: 1. **Structure:** which operator owns which operands? (`2 + 3 * 4` -> `2 + (3 * 4)`.) This is answered by **precedence** and **associativity**. 2. **Timeline:** in what order do the operands actually get computed (which matters only when they have **side effects** — things like method calls, assignments, or `++`)? This is answered by **evaluation order**. Many developers assume that the higher-precedence operator's operands are computed first. That is wrong. Precedence builds the parse tree; it says nothing about the clock. ## Java's evaluation-order guarantee Java specifies that the operands of a binary operator are evaluated **left operand first, then right operand**, and the left is *fully* evaluated (including all its side effects) before the right begins. Argument lists are evaluated left to right too. Array indexing evaluates the array reference before the index. This is a hard guarantee in the Java Language Specification — unlike C and C++, which leave much of it unspecified. ## Worked example with side effects ```java static int log(int v, String tag) { System.out.println(tag); return v; } int x = log(2, "A") + log(3, "B") * log(4, "C"); ``` - **Precedence** groups it as `log(2,"A") + (log(3,"B") * log(4,"C"))`. So the multiplication node sits below the addition node in the tree. - **Evaluation order** prints `A`, then `B`, then `C` — strict left to right — regardless of the fact that `*` is the higher-precedence (deeper) node. The final value is `2 + (3 * 4) = 14`. So the *value* comes from the grouping (14), but the *order of side effects* comes from left-to-right (A, B, C). ## The classic i = i++ + ++i ```java int i = 1; i = i++ + ++i; // i becomes 4 ``` Left to right: `i++` reads 1 and post-increments i to 2 (its value is 1); then `++i` pre-increments i to 3 (its value is 3); the sum is `1 + 3 = 4`; that 4 is assigned to i (overwriting 3). In C/C++ this is undefined behavior; in Java it is fully defined because evaluation order is pinned. (It is still terrible code — never write it — but it demonstrates the guarantee.) ## Why this matters in practice - Reasoning about expressions that mix method calls with operators (logging order, exception ordering, lazily-built state). - Understanding short-circuit operators: `&&`/`||` add the extra rule that the right operand may be **skipped** entirely, which is an evaluation-order concern layered on top of precedence. - Porting code from C/C++: order-dependent expressions that were UB there are defined in Java, but still fragile. ## Deriving the answer Ask two questions separately: 'How does it group?' (precedence/associativity) and 'In what order do side effects fire?' (always left to right in Java). Keep them apart and the trickiest expressions become mechanical.
- Why is i = i++ + ++i deterministic in Java but undefined in C/C++?Java's specification mandates strict left-to-right operand evaluation and well-defined sequencing of the increment side effects, so the result (4 from i=1) is fixed. C/C++ leave the relative ordering of those side effects unspecified, making the expression undefined behavior.
- How do short-circuit operators interact with evaluation order?&& and || evaluate the left operand first (left to right), then conditionally skip the right operand entirely if the result is already determined. That conditional skipping is an evaluation-order rule layered on top of precedence, not a precedence rule itself.
saying these in an interview costs you the question
- Saying the higher-precedence operator's operands are computed first in time
- Claiming i = i++ + ++i is undefined behavior in Java (it is in C/C++, defined in Java)
- Believing evaluation order is unspecified or compiler-dependent in Java
- Confusing short-circuit skipping with precedence