Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Java process the expression x = x - (x = x - 1)?

I just tested the following code:

int x = 90;

x = x - (x = x - 1);
System.out.print(x);

It prints 1.

As far as I understand, things go in the following order:

  1. x - 1 is computed and stored to a temporary variable in memory.
  2. x is assigned the result from the temporary variable from item 1.
  3. Then x - the new value of x is calculated.
  4. The result is assigned to x;

I don't understand why x from which we subtract the result of item 2 still has initial value after item 2. What am I missing?

like image 674
Maksim Dmitriev Avatar asked Feb 06 '23 18:02

Maksim Dmitriev


2 Answers

From https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

All binary operators except for the assignment operators are evaluated from left to right; assignment operators are evaluated right to left.

You are doing 90 - (90 - 1) => 1

It's important to not confuse precedence with order of evaluation. They are related but not the same.


EDIT

As @ruakh points out, the JLS spec put it differently to the tutorial above.

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15‌​.7.

The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.

If the operator is a compound-assignment operator (§15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied binary operation.

If evaluation of the left-hand operand of a binary operator completes abruptly, no part of the right-hand operand appears to have been evaluated.

Rather than say the assignment is evaluated right to left, it treats assignment as first a store of the variable to be updated, then an evaluation of the value and finally an assignment.

like image 131
Peter Lawrey Avatar answered Feb 08 '23 06:02

Peter Lawrey


We start with:

int x = 90;
x = x - (x = x - 1);

The first assignment operator = has low precedence, so the right side is evaluated first.

The right side of x = x - (x = x - 1) is x - b where b is (x = x - 1)

This right side is evaluated left to right, so it becomes 90 - b

Then b, which is (x = x - 1), is evaluated. Once again the assignment operator has lowest precedence, so it becomes (x = 90 - 1) or (x = 89)

Substituting back, we have 90 - (x = 89) which is 90 - 89 which is 1. Finally, the first assignment operator is evaluated and x becomes 1. You'll notice that the other assignment operator (x = 89) had no effect on the overall operation.

like image 32
Sean F Avatar answered Feb 08 '23 08:02

Sean F