Consider the following example:
class Quirky {
public static void main(String[] args) {
int x = 1;
int y = 3;
System.out.println(x =
Basically the first statement x had it's value 1 So Java compares 1 == to new x variable which won't be the same
In the second one you said x=y which means the value of x changed and so when you call it again it'll be the same value hence why it's true and x ==x
I'm not sure if there is an item in the Java Language Specification that dictates loading the previous value of a variable...
There is. Next time you are unclear what the specification says, please read the specification and then ask the question if it is unclear.
... the right side
(x = y)
which, by the order implied by brackets, should be calculated first.
That statement is false. Parentheses do not imply an order of evaluation. In Java, the order of evaluation is left to right, regardless of parentheses. Parentheses determine where the subexpression boundaries are, not the order of evaluation.
Why does the first expression evaluate to false, but the second evaluate to true?
The rule for the ==
operator is: evaluate the left side to produce a value, evaluate the right side to produce a value, compare the values, the comparison is the value of the expression.
In other words, the meaning of expr1 == expr2
is always the same as though you had written temp1 = expr1; temp2 = expr2;
and then evaluated temp1 == temp2
.
The rule for the =
operator with a local variable on the left side is: evaluate the left side to produce a variable, evaluate the right side to produce a value, perform the assignment, the result is the value that was assigned.
So put it together:
x == (x = y)
We have a comparison operator. Evaluate the left side to produce a value -- we get the current value of x
. Evaluate the right side: that's an assignment so we evaluate the left side to produce a variable -- the variable x
-- we evaluate the right side -- the current value of y
-- assign it to x
, and the result is the assigned value. We then compare the original value of x
to the value that was assigned.
You can do (x = y) == x
as an exercise. Again, remember, all the rules for evaluating the left side happen before all the rules of evaluating the right side.
I would have expected (x = y) to be evaluated first, and then it would compare x with itself (3) and return true.
Your expectation is based on a set of incorrect beliefs about the rules of Java. Hopefully you now have correct beliefs and will in the future expect true things.
This question is different from "order of evaluation of subexpressions in a Java expression"
This statement is false. That question is totally germane.
x is definitely not a 'subexpression' here.
This statement is also false. It is a subexpression twice in each example.
It needs to be loaded for the comparison rather than to be 'evaluated'.
I have no idea what this means.
Apparently you still have many false beliefs. My advice is that you read the specification until your false beliefs are replaced by true beliefs.
The question is Java-specific and the expression x == (x = y), unlike far-fetched impractical constructs commonly crafted for tricky interview questions, came from a real project.
The provenance of the expression is not relevant to the question. The rules for such expressions are clearly described in the specification; read it!
It was supposed to be a one-line replacement for the compare-and-replace idiom
Since that one-line replacement caused a great deal of confusion in you, the reader of the code, I would suggest that it was a poor choice. Making the code more concise but harder to understand is not a win. It is unlikely to make the code faster.
Incidentally, C# has compare and replace as a library method, which can be jitted down to a machine instruction. I believe Java does not have such a method, as it cannot be represented in the Java type system.
The kind of question you asked is a very good question if you want to write a Java compiler, or test programs to verify that a Java compiler is working correctly. In Java, these two expressions must produce the results that you saw. In C++, for example, they don't have to - so if someone reused parts of a C++ compiler in their Java compiler, you might theoretically find that the compiler doesn't behave as it should.
As a software developer, writing code that is readable, understandable and maintainable, both versions of your code would be considered awful. To understand what the code does, one has to know exactly how the Java language is defined. Someone who writes both Java and C++ code would shudder looking at the code. If you have to ask why a single line of code does what it does, then you should avoid that code. (I suppose and hope that the guys who answered your "why" question correctly will themselves avoid that ind of code as well).
As LouisWasserman said, the expression is evaluated left to right. And java doesn't care what "evaluate" actually does, it only cares about generating a (non volatile, final) value to work with.
//the example values
x = 1;
y = 3;
So to calculate the first output of System.out.println()
, the following is done:
x == (x = y)
1 == (x = y)
1 == (x = 3) //assign 3 to x, returns 3
1 == 3
false
and to calculate the second:
(x = y) == x
(x = 3) == x //assign 3 to x, returns 3
3 == x
3 == 3
true
Note that the second value will always evaluate to true, regardless of the initial values of x
and y
, because you are effectively comparing the assignment of a value to the variable it is assigned to, and a = b
and b
will, evaluated in that order, always be the same by definition.
In the first test you're checking does 1 == 3.
In the second test your checking does 3 == 3.
(x = y) assigns the value and that value is tested. In the former example x = 1 first then x is assigned 3. Does 1 == 3?
In the latter, x is assigned 3, and obviously it's still 3. Does 3 == 3?
It is easy in the second comparison on the left is assignment after assigning y to x (on the left) you then comparing 3 == 3. In the first example you are comparing x = 1 with new assign x = 3. It seems that there is always taken current state reading statements from left to right of x.