I have an expression with compound assignment as
x += 2*5
so how it will be evaluated is it
x = (x + 2) * 5
or
x = x + (2 * 5)
and why?
An expression of the form
x += expr;
is equivalent to
x = x + (expr);
So in this case it's
x = x + (2 * 5);
It would be very weird and confusing if the current value of x was used for part of the expression implicitly.
Any expression in the form of var op= expr is evaluated to var = var op expr. This is defined in the java specification 15.26.2 Compound Assignment Operators.
I see the phrase "operator precedence" mentioned, and I believe this is confusing the issue. Consider this:
x *= a + b;
Even though * has a higher precedence than +, this is still evaluated as
x = x * (a + b)
The full explanation is given in JLS 15.26.2 Compound Assignment Operatos:
E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once
Related
This question already has answers here:
Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
(11 answers)
Closed 5 years ago.
i know that by default numbers are stored as integer in java but
byte x = 10;
x = x + 10;
is giving error while
byte x = 10;
x += 10;
is compiling fine
JLS have an answer for you
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.
short x = 3;
x += 4.6;
and results in x having the value 7 because it is equivalent to:
short x = 3;
x = (short)(x + 4.6);
So in your case your second statement equlas to
x = (byte) x + 10;
That is the reason compiler is happy about.
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:
x - 1 is computed and stored to a temporary variable in memory.
x is assigned the result from the temporary variable from item 1.
Then x - the new value of x is calculated.
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?
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.
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.
int x = 90;
x = x - (x = x - 1);
System.out.print(x);`
Here
x = 90 Goes in two section in your code.
First x=90 - , Second (x=90-1);
Then x=90 - , x = 89
Then x= 90 - 89
System.out.Print(x);
that is x=1;
Consider the following pseudo-code:
int x = 10;
int y = 10;
x = x + x++;
y = y++ + y;
print(x); // 20
print(y); // 21
C-like programming languages like C# or Java say that increment has higher precedence, than + operator. So it should be 21 in both cases.
Why does it print two different results?
Remember we work from left to right.
Let's deal with x first then y.
x
x = x + x++;
We are going from left to right...
x = 10 + (10++)
Note: As we go from left to right the post increment operator on x on the far right has no effect on the x which appears first on the RHS.
x = 20
y
y = y++ + y;
y = 10++ + 11;
Again we go from left to right, the increment operator post increments y from 10 to 11, hence the y on the far right becomes 11, thus yielding (10 + 11) = 21.
When y++ + y is evaluated, y++ is evaluated before y. So the left hand side is evaluated to 10, and the right hand side will be evaluated to 11 due to the previous incrementation.
When x + x++ is evaluated, x is evaluated before x++. So both sides will be evaluated to 10, then x will be evaluated to 11 just before the = operand will evaluate x to 20.
I believe the + operator has higher precedence than ++, so the + operator is evaluated first, but in order to evaluate it - it must evaluate the left and right operators of it.
In the second example the left operator is evaluated first so y increments before the right hand is evaluated.
In the Precedence and Order of Evaluation documentation, you can see that + is above += which is basically what ++ is. Above the + is the prefix ++ which is not to be confused with the postfix ++.
int anInt = 1;
double aDouble = 2.5;
anInt = anInt + aDouble; // Error - need to cast double to int
anInt += aDouble; // This is ok. Why?
anInt = aDouble; // This is also an error.
anInt = 1 + aDouble; // This is also an error.
So my questions is: Why is it not a compile error to do anInt += aDouble?
Three of the four cases properly report an error. Compound assignment is the only exception from the rule. Java Language Specification, part 15.26.2, explains why:
15.26.2 Compound Assignment Operators
A compound assignment expression of the form E1 op= E2 is equivalent to E1
= (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.
For example, the following code is correct:
short x = 3;
x += 4.6;
and results in x having the value 7 because it is equivalent to:
short x = 3;
x = (short)(x + 4.6);
As you can see, the error is avoided by implicit insertion of a cast.
I don`t understand how Java is progressing this arithmetic expression
int x = 1;
int y = 1;
x += y += x += y;
System.out.println("x=" + x + " y=" + y);
With Java I get x = 4 and y = 3. But in C, Perl, Php I get x=5 and y = 3
On the paper I also get x = 5 and y = 3
This is the nasty part, obviously:
x += y += x += y;
This is executed as:
int originalX = x; // Used later
x = x + y; // Right-most x += y
y = y + x; // Result of "x += y" is the value stored in x
x = originalX + y; // Result of "y += x" is the value stored in y
So:
x y
(Start) 1 1
x = x + y 2 1
y = y + x 2 3
x = originalX + y 4 3
The important part is the use of originalX here. The compound assignment is treated as:
x = x + y
and the first operand of + is evaluated before the second operand... which is why it takes the original value of x, not the "latest" one.
From JLS section 15.16.2:
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.
When in doubt, consult the language specification - and never assume that just because two languages behave differently, one of them is "wrong". So long as the actual behaviour matches the specified behaviour for each language, all is well - but it does mean you need to understand the behaviour of each language you work with, of course.
That said, you should clearly avoid horrible code like this in the first place.
it starts from right to left
1. x += y gives x = 2, y = 1
2. y += ( x +=y ) gives x = 2, y = 3
3. x += ( y += x += y ) gives x = 4, y = 3
so, it's all consistent