skip to content

How does operator precedence differ from operand evaluation order in Java? Use an expression with side effects to illustrate.

level: seniorimportance: should knowfreq 45%

answer

  1. Precedence = structure (parse tree)
  2. Evaluation order = timeline (left to right)
  3. Higher precedence != evaluated first
  4. Java pins left-to-right; C/C++ does not
  5. Side effects expose the difference

basics

~20 s

Precedence 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 s

These 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 lines
java
static 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); // 14

go deeper

for a junior

May not need this distinction yet, but should at least know operands run left to right.

for a middle

States that precedence is about grouping and Java evaluates left to right, and can trace a simple side-effecting expression.

for a senior

Cleanly separates parse-tree structure from runtime timeline, cites Java's strict left-to-right guarantee, and explains i = i++ + ++i and short-circuiting.

for a principal

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

context