This has to do with evaluation of operands taking place before order of operators (precedence).
Before operators are executed, the operands are evaluated, which in Java always take place in a left-to-right order.
The leftmost A
is evaluated as 5
, then the leftmost B
is 2
, then the second A
is 5
and the second B
is also 2
. These values are saved for later computation.
The JLS, Section 15.26.2, deals with the procedure of evaluating a compound assignment operator.
If the left-hand operand expression is not an array access expression, then:
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.
Otherwise, the result of the binary operation is converted to the type of the left-hand variable, subjected to value set conversion (§5.1.13) to the appropriate standard value set (not an extended-exponent value set), and the result of the conversion is stored into the variable.
(bold emphasis mine)
Then the operators are executed, with *=
having right-associativity. This means that operation proceeds right-to-left. The rightmost A *= B
is executed, assigning 10
to A
. The the middle B *= A
is executed, assigning 20
to B
. However, when the leftmost A *= B
is executed, the saved value of A
is still there -- 5
. When multiplied by 20
, 100
is assigned to A
.
A *= B*= A *= B; // A is now 100
If we break this up into 3 statements, then you will get the expected 200
, because A
will be evaluated again as part of the last statement as 10
, not 5
, because the saved value for A
is now 10
.
A *= B;
B *= A;
A *= B; // A is now 200
A *=
uses the original value ofA
, not the result from later operations – Cristencristi