First thing to notice here is that you're not doing a simple multiplication, you're using a compound assignment operator
, that is an operator that encapsulates performing an operation on a variable and then assigning the result to the original variable.
From the JLS section about compound assignment operators (like *=
):
First, the left-hand operand is evaluated to produce a variable. If
this evaluation completes abruptly, then the assignment expression
completes abruptly for the same reason; the right-hand operand is not
evaluated and no assignment occurs.
Otherwise, the value of the left-hand operand is saved and then the
right-hand operand is evaluated. If this evaluation completes
abruptly, then the assignment expression completes abruptly for the
same reason and no assignment occurs.
- Otherwise, the saved value of the left-hand variable and the value of the right-hand operand are used to perform the binary operation indicated by the compound assignment operator. If this operation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.
The highlighted text guarantees that on the left hand side of the multiplication the original value of i
will be used, that is 10. (And the right hand side evaluates to 21, as you correctly derived already.)
The other, arguably more important lesson is that operator precedence is not the same as evaluation order. Precedence is only used to parse the expression into an expression tree but operators are always evaluated from left to right, and from the outside in.
In your case the expression tree looks roughly like this (note how the lowest precedence operator ends up at the root of the tree):
*=
/ \
i +
/ \
i++ i
...and now it is evaluated from the top to bottom, left-to-right like this:
*= *= *= *= 210
/ \ / \ / \ / \
10 + -> 10 + -> 10 + -> 10 21 ->
/ \ / \ / \
i++ i 10 i 10 11