Why is x == (x = y) not the same as (x = y) == x?
up vote
48
down vote
favorite
Consider the following example:
class Quirky {
public static void main(String args) {
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
x = 1; // reset
System.out.println((x = y) == x); // true
}
}
I'm not sure if there is an item in the Java Language Specification that dictates loading the previous value of a variable for comparison with the right side (x = y
) which, by the order implied by brackets, should be calculated first.
Why does the first expression evaluate to false
, but the second evaluate to true
? I would have expected (x = y)
to be evaluated first, and then it would compare x
with itself (3
) and return true
.
This question is different from order of evaluation of subexpressions in a Java expression in that x
is definitely not a 'subexpression' here. It needs to be loaded for the comparison rather than to be 'evaluated'. 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. It was supposed to be a one-line replacement for the compare-and-replace idiom
int oldX = x;
x = y;
return oldX == y;
which, being even simpler than x86 CMPXCHG instruction, deserved a shorter expression in Java.
java variable-assignment operator-precedence jls
|
show 13 more comments
up vote
48
down vote
favorite
Consider the following example:
class Quirky {
public static void main(String args) {
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
x = 1; // reset
System.out.println((x = y) == x); // true
}
}
I'm not sure if there is an item in the Java Language Specification that dictates loading the previous value of a variable for comparison with the right side (x = y
) which, by the order implied by brackets, should be calculated first.
Why does the first expression evaluate to false
, but the second evaluate to true
? I would have expected (x = y)
to be evaluated first, and then it would compare x
with itself (3
) and return true
.
This question is different from order of evaluation of subexpressions in a Java expression in that x
is definitely not a 'subexpression' here. It needs to be loaded for the comparison rather than to be 'evaluated'. 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. It was supposed to be a one-line replacement for the compare-and-replace idiom
int oldX = x;
x = y;
return oldX == y;
which, being even simpler than x86 CMPXCHG instruction, deserved a shorter expression in Java.
java variable-assignment operator-precedence jls
38
The left hand side is always evaluated before the right hand side. The brackets don't make a difference to that.
– Louis Wasserman
yesterday
6
Evaluating the expressionx = y
is certainly relevant, and causes the side effect thatx
is set to the value ofy
.
– Louis Wasserman
yesterday
22
Do yourself and your teammates a favor and don't mix state mutation into the same line as state examination. Doing so drastically reduces the readability of your code. (There are some cases where it's absolutely necessary because of atomicity requirements, but functions for those already exist and their purpose would be instantly recognized.)
– jpmc26
yesterday
20
The real question is why you want to write code like this.
– Broman
yesterday
9
The key to your question is your false belief that parentheses imply evaluation order. That is a common belief because of how we're taught math in elementary school and because some beginner programming books still get it wrong, but it is a false belief. This is a pretty frequent question. You might benefit from reading my articles on the subject; they are about C# but they apply to Java: ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order ericlippert.com/2009/08/10/precedence-vs-order-redux
– Eric Lippert
15 hours ago
|
show 13 more comments
up vote
48
down vote
favorite
up vote
48
down vote
favorite
Consider the following example:
class Quirky {
public static void main(String args) {
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
x = 1; // reset
System.out.println((x = y) == x); // true
}
}
I'm not sure if there is an item in the Java Language Specification that dictates loading the previous value of a variable for comparison with the right side (x = y
) which, by the order implied by brackets, should be calculated first.
Why does the first expression evaluate to false
, but the second evaluate to true
? I would have expected (x = y)
to be evaluated first, and then it would compare x
with itself (3
) and return true
.
This question is different from order of evaluation of subexpressions in a Java expression in that x
is definitely not a 'subexpression' here. It needs to be loaded for the comparison rather than to be 'evaluated'. 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. It was supposed to be a one-line replacement for the compare-and-replace idiom
int oldX = x;
x = y;
return oldX == y;
which, being even simpler than x86 CMPXCHG instruction, deserved a shorter expression in Java.
java variable-assignment operator-precedence jls
Consider the following example:
class Quirky {
public static void main(String args) {
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
x = 1; // reset
System.out.println((x = y) == x); // true
}
}
I'm not sure if there is an item in the Java Language Specification that dictates loading the previous value of a variable for comparison with the right side (x = y
) which, by the order implied by brackets, should be calculated first.
Why does the first expression evaluate to false
, but the second evaluate to true
? I would have expected (x = y)
to be evaluated first, and then it would compare x
with itself (3
) and return true
.
This question is different from order of evaluation of subexpressions in a Java expression in that x
is definitely not a 'subexpression' here. It needs to be loaded for the comparison rather than to be 'evaluated'. 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. It was supposed to be a one-line replacement for the compare-and-replace idiom
int oldX = x;
x = y;
return oldX == y;
which, being even simpler than x86 CMPXCHG instruction, deserved a shorter expression in Java.
java variable-assignment operator-precedence jls
java variable-assignment operator-precedence jls
edited 2 hours ago
asked yesterday
John McClane
626314
626314
38
The left hand side is always evaluated before the right hand side. The brackets don't make a difference to that.
– Louis Wasserman
yesterday
6
Evaluating the expressionx = y
is certainly relevant, and causes the side effect thatx
is set to the value ofy
.
– Louis Wasserman
yesterday
22
Do yourself and your teammates a favor and don't mix state mutation into the same line as state examination. Doing so drastically reduces the readability of your code. (There are some cases where it's absolutely necessary because of atomicity requirements, but functions for those already exist and their purpose would be instantly recognized.)
– jpmc26
yesterday
20
The real question is why you want to write code like this.
– Broman
yesterday
9
The key to your question is your false belief that parentheses imply evaluation order. That is a common belief because of how we're taught math in elementary school and because some beginner programming books still get it wrong, but it is a false belief. This is a pretty frequent question. You might benefit from reading my articles on the subject; they are about C# but they apply to Java: ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order ericlippert.com/2009/08/10/precedence-vs-order-redux
– Eric Lippert
15 hours ago
|
show 13 more comments
38
The left hand side is always evaluated before the right hand side. The brackets don't make a difference to that.
– Louis Wasserman
yesterday
6
Evaluating the expressionx = y
is certainly relevant, and causes the side effect thatx
is set to the value ofy
.
– Louis Wasserman
yesterday
22
Do yourself and your teammates a favor and don't mix state mutation into the same line as state examination. Doing so drastically reduces the readability of your code. (There are some cases where it's absolutely necessary because of atomicity requirements, but functions for those already exist and their purpose would be instantly recognized.)
– jpmc26
yesterday
20
The real question is why you want to write code like this.
– Broman
yesterday
9
The key to your question is your false belief that parentheses imply evaluation order. That is a common belief because of how we're taught math in elementary school and because some beginner programming books still get it wrong, but it is a false belief. This is a pretty frequent question. You might benefit from reading my articles on the subject; they are about C# but they apply to Java: ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order ericlippert.com/2009/08/10/precedence-vs-order-redux
– Eric Lippert
15 hours ago
38
38
The left hand side is always evaluated before the right hand side. The brackets don't make a difference to that.
– Louis Wasserman
yesterday
The left hand side is always evaluated before the right hand side. The brackets don't make a difference to that.
– Louis Wasserman
yesterday
6
6
Evaluating the expression
x = y
is certainly relevant, and causes the side effect that x
is set to the value of y
.– Louis Wasserman
yesterday
Evaluating the expression
x = y
is certainly relevant, and causes the side effect that x
is set to the value of y
.– Louis Wasserman
yesterday
22
22
Do yourself and your teammates a favor and don't mix state mutation into the same line as state examination. Doing so drastically reduces the readability of your code. (There are some cases where it's absolutely necessary because of atomicity requirements, but functions for those already exist and their purpose would be instantly recognized.)
– jpmc26
yesterday
Do yourself and your teammates a favor and don't mix state mutation into the same line as state examination. Doing so drastically reduces the readability of your code. (There are some cases where it's absolutely necessary because of atomicity requirements, but functions for those already exist and their purpose would be instantly recognized.)
– jpmc26
yesterday
20
20
The real question is why you want to write code like this.
– Broman
yesterday
The real question is why you want to write code like this.
– Broman
yesterday
9
9
The key to your question is your false belief that parentheses imply evaluation order. That is a common belief because of how we're taught math in elementary school and because some beginner programming books still get it wrong, but it is a false belief. This is a pretty frequent question. You might benefit from reading my articles on the subject; they are about C# but they apply to Java: ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order ericlippert.com/2009/08/10/precedence-vs-order-redux
– Eric Lippert
15 hours ago
The key to your question is your false belief that parentheses imply evaluation order. That is a common belief because of how we're taught math in elementary school and because some beginner programming books still get it wrong, but it is a false belief. This is a pretty frequent question. You might benefit from reading my articles on the subject; they are about C# but they apply to Java: ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order ericlippert.com/2009/08/10/precedence-vs-order-redux
– Eric Lippert
15 hours ago
|
show 13 more comments
7 Answers
7
active
oldest
votes
up vote
66
down vote
==
is a binary equality operator.
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
Java 11 Specification > Evaluation Order > Evaluate Left-Hand Operand First
9
The wording "appears to be" doesn't sound like they're sure, tbh.
– Mr Lister
19 hours ago
28
"appears to be" means the specification does not require that the operations are actually carried out in that order chronologically, but it requires that you get the same result that you would get if they were.
– Robyn
18 hours ago
7
@MrLister "appears to be" appears to be a poor word choice on their part. By "appear" they mean "manifest as a phenomenon to the developer". "is effectively" may be a better phrase.
– Kelvin
12 hours ago
2
in the C++ community this is the equivalent to the "as-if" rule... the operand is required to behave "as if" it was implemented per the following rules, even if technically it is not.
– Michael Edenfield
8 hours ago
add a comment |
up vote
50
down vote
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 = 2;
So in quickReplaceAndCompare()
the following is done:
x == (x = y)
1 == (x = y)
1 == (x = 2) //assign 2 to x, returns 2
1 == 2
false
and in badReplaceAndCompare()
:
(x = y) == x
(x = 2) == x //assign 2 to x, returns 2
2 == x
2 == 2
true
Note that badReplaceAndCompare()
will always return true, 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.
fyi, I edited out those functions from his question
– pushkin
10 hours ago
add a comment |
up vote
12
down vote
which, by the order implied by brackets, should be calculated first
No. It is a common misconception that parentheses have any (general) effect on calculation or evaluation order. They only coerce the parts of your expression into a particular tree, binding the right operands to the right operations for the job.
(And, if you don't use them, this information comes from the "precedence" and associativity of the operators, something that's a result of how the language's syntax tree is defined. In fact, this is still exactly how it works when you use parentheses, but we simplify and say that we're not relying on any precedence rules then.)
Once that's done (i.e. once your code has been parsed into a program) those operands still need to be evaluated, and there are separate rules about how that is done: said rules (as Andrew has shown us) state that the LHS of each operation is evaluated first in Java.
Note that this is not the case in all languages; for example, in C++, unless you're using a short-circuiting operator like &&
or ||
, the evaluation order of operands is generally unspecified and you shouldn't rely on it either way.
Teachers need to stop explaining operator precedence using misleading phrases like "this makes the addition happen first". Given an expression x * y + z
the proper explanation would be "operator precedence makes the addition happen between x * y
and z
, rather than between y
and z
", with no mention of any "order".
1
I wish my teachers had made some separation between the underlying math and the syntax they used to represent it, like if we spent a day with Roman numerals or Polish notation or whatever and saw that addition has the same properties. We learned associativity and all those properties in middle school, so there was plenty of time.
– John P
6 hours ago
add a comment |
up vote
1
down vote
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?
add a comment |
up vote
1
down vote
It is related to operator precedence and how operators are getting evaluated.
Parentheses '()' has higher precedence and has associativity left to right.
Equality '==' come next in this question and has associativity left to right.
Assignment '=' come last and has associativity right to left.
System use stack to evaluate expression. Expression gets evaluated left to right.
Now comes to original question:
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
First x(1) will be pushed to stack.
then inner (x = y) will be evaluated and pushed to stack with value x(3).
Now x(1) will be compared against x(3) so result is false.
x = 1; // reset
System.out.println((x = y) == x); // true
Here,
(x = y) will be evaluated, now x value become 3 and x(3) will be pushed to stack.
Now x(3) with changed value after equality will be pushed to stack.
Now expression will be evaluated and both will be same so result is true.
New contributor
2
"Assignment '=' come last and evaluated right to left." That's incorrect, or misleading. Assignments are right-to-left associative, which affects grouping in larger expressions, but their operands are evaluated left-to-right. Also see this answer and Precedence vs Associativity vs Order by Eric Lippert. Precedence isn't whyx==(x=y)
and(x=y)==x
have different results.
– Radiodef
9 hours ago
@Radiodef, You are correct, updated my answer.
– Amit
1 hour ago
add a comment |
up vote
0
down vote
It is not the same. The left hand side will always be evaluated before the right hand side, and the brackets don't specify an order of execution, but a grouping of commands.
With:
x == (x = y)
You are basically doing the same as:
x == y
And x will have the value of y after the comparison.
While with:
(x = y) == x
You are basically doing the same as:
x == x
After x took y's value. And it will always return true.
add a comment |
up vote
0
down vote
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
New contributor
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53749841%2fwhy-is-x-x-y-not-the-same-as-x-y-x%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
66
down vote
==
is a binary equality operator.
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
Java 11 Specification > Evaluation Order > Evaluate Left-Hand Operand First
9
The wording "appears to be" doesn't sound like they're sure, tbh.
– Mr Lister
19 hours ago
28
"appears to be" means the specification does not require that the operations are actually carried out in that order chronologically, but it requires that you get the same result that you would get if they were.
– Robyn
18 hours ago
7
@MrLister "appears to be" appears to be a poor word choice on their part. By "appear" they mean "manifest as a phenomenon to the developer". "is effectively" may be a better phrase.
– Kelvin
12 hours ago
2
in the C++ community this is the equivalent to the "as-if" rule... the operand is required to behave "as if" it was implemented per the following rules, even if technically it is not.
– Michael Edenfield
8 hours ago
add a comment |
up vote
66
down vote
==
is a binary equality operator.
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
Java 11 Specification > Evaluation Order > Evaluate Left-Hand Operand First
9
The wording "appears to be" doesn't sound like they're sure, tbh.
– Mr Lister
19 hours ago
28
"appears to be" means the specification does not require that the operations are actually carried out in that order chronologically, but it requires that you get the same result that you would get if they were.
– Robyn
18 hours ago
7
@MrLister "appears to be" appears to be a poor word choice on their part. By "appear" they mean "manifest as a phenomenon to the developer". "is effectively" may be a better phrase.
– Kelvin
12 hours ago
2
in the C++ community this is the equivalent to the "as-if" rule... the operand is required to behave "as if" it was implemented per the following rules, even if technically it is not.
– Michael Edenfield
8 hours ago
add a comment |
up vote
66
down vote
up vote
66
down vote
==
is a binary equality operator.
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
Java 11 Specification > Evaluation Order > Evaluate Left-Hand Operand First
==
is a binary equality operator.
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
Java 11 Specification > Evaluation Order > Evaluate Left-Hand Operand First
edited yesterday
answered yesterday
Andrew Tobilko
24.5k84182
24.5k84182
9
The wording "appears to be" doesn't sound like they're sure, tbh.
– Mr Lister
19 hours ago
28
"appears to be" means the specification does not require that the operations are actually carried out in that order chronologically, but it requires that you get the same result that you would get if they were.
– Robyn
18 hours ago
7
@MrLister "appears to be" appears to be a poor word choice on their part. By "appear" they mean "manifest as a phenomenon to the developer". "is effectively" may be a better phrase.
– Kelvin
12 hours ago
2
in the C++ community this is the equivalent to the "as-if" rule... the operand is required to behave "as if" it was implemented per the following rules, even if technically it is not.
– Michael Edenfield
8 hours ago
add a comment |
9
The wording "appears to be" doesn't sound like they're sure, tbh.
– Mr Lister
19 hours ago
28
"appears to be" means the specification does not require that the operations are actually carried out in that order chronologically, but it requires that you get the same result that you would get if they were.
– Robyn
18 hours ago
7
@MrLister "appears to be" appears to be a poor word choice on their part. By "appear" they mean "manifest as a phenomenon to the developer". "is effectively" may be a better phrase.
– Kelvin
12 hours ago
2
in the C++ community this is the equivalent to the "as-if" rule... the operand is required to behave "as if" it was implemented per the following rules, even if technically it is not.
– Michael Edenfield
8 hours ago
9
9
The wording "appears to be" doesn't sound like they're sure, tbh.
– Mr Lister
19 hours ago
The wording "appears to be" doesn't sound like they're sure, tbh.
– Mr Lister
19 hours ago
28
28
"appears to be" means the specification does not require that the operations are actually carried out in that order chronologically, but it requires that you get the same result that you would get if they were.
– Robyn
18 hours ago
"appears to be" means the specification does not require that the operations are actually carried out in that order chronologically, but it requires that you get the same result that you would get if they were.
– Robyn
18 hours ago
7
7
@MrLister "appears to be" appears to be a poor word choice on their part. By "appear" they mean "manifest as a phenomenon to the developer". "is effectively" may be a better phrase.
– Kelvin
12 hours ago
@MrLister "appears to be" appears to be a poor word choice on their part. By "appear" they mean "manifest as a phenomenon to the developer". "is effectively" may be a better phrase.
– Kelvin
12 hours ago
2
2
in the C++ community this is the equivalent to the "as-if" rule... the operand is required to behave "as if" it was implemented per the following rules, even if technically it is not.
– Michael Edenfield
8 hours ago
in the C++ community this is the equivalent to the "as-if" rule... the operand is required to behave "as if" it was implemented per the following rules, even if technically it is not.
– Michael Edenfield
8 hours ago
add a comment |
up vote
50
down vote
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 = 2;
So in quickReplaceAndCompare()
the following is done:
x == (x = y)
1 == (x = y)
1 == (x = 2) //assign 2 to x, returns 2
1 == 2
false
and in badReplaceAndCompare()
:
(x = y) == x
(x = 2) == x //assign 2 to x, returns 2
2 == x
2 == 2
true
Note that badReplaceAndCompare()
will always return true, 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.
fyi, I edited out those functions from his question
– pushkin
10 hours ago
add a comment |
up vote
50
down vote
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 = 2;
So in quickReplaceAndCompare()
the following is done:
x == (x = y)
1 == (x = y)
1 == (x = 2) //assign 2 to x, returns 2
1 == 2
false
and in badReplaceAndCompare()
:
(x = y) == x
(x = 2) == x //assign 2 to x, returns 2
2 == x
2 == 2
true
Note that badReplaceAndCompare()
will always return true, 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.
fyi, I edited out those functions from his question
– pushkin
10 hours ago
add a comment |
up vote
50
down vote
up vote
50
down vote
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 = 2;
So in quickReplaceAndCompare()
the following is done:
x == (x = y)
1 == (x = y)
1 == (x = 2) //assign 2 to x, returns 2
1 == 2
false
and in badReplaceAndCompare()
:
(x = y) == x
(x = 2) == x //assign 2 to x, returns 2
2 == x
2 == 2
true
Note that badReplaceAndCompare()
will always return true, 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.
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 = 2;
So in quickReplaceAndCompare()
the following is done:
x == (x = y)
1 == (x = y)
1 == (x = 2) //assign 2 to x, returns 2
1 == 2
false
and in badReplaceAndCompare()
:
(x = y) == x
(x = 2) == x //assign 2 to x, returns 2
2 == x
2 == 2
true
Note that badReplaceAndCompare()
will always return true, 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.
edited 14 hours ago
Hulk
2,49311635
2,49311635
answered yesterday
Poohl
493310
493310
fyi, I edited out those functions from his question
– pushkin
10 hours ago
add a comment |
fyi, I edited out those functions from his question
– pushkin
10 hours ago
fyi, I edited out those functions from his question
– pushkin
10 hours ago
fyi, I edited out those functions from his question
– pushkin
10 hours ago
add a comment |
up vote
12
down vote
which, by the order implied by brackets, should be calculated first
No. It is a common misconception that parentheses have any (general) effect on calculation or evaluation order. They only coerce the parts of your expression into a particular tree, binding the right operands to the right operations for the job.
(And, if you don't use them, this information comes from the "precedence" and associativity of the operators, something that's a result of how the language's syntax tree is defined. In fact, this is still exactly how it works when you use parentheses, but we simplify and say that we're not relying on any precedence rules then.)
Once that's done (i.e. once your code has been parsed into a program) those operands still need to be evaluated, and there are separate rules about how that is done: said rules (as Andrew has shown us) state that the LHS of each operation is evaluated first in Java.
Note that this is not the case in all languages; for example, in C++, unless you're using a short-circuiting operator like &&
or ||
, the evaluation order of operands is generally unspecified and you shouldn't rely on it either way.
Teachers need to stop explaining operator precedence using misleading phrases like "this makes the addition happen first". Given an expression x * y + z
the proper explanation would be "operator precedence makes the addition happen between x * y
and z
, rather than between y
and z
", with no mention of any "order".
1
I wish my teachers had made some separation between the underlying math and the syntax they used to represent it, like if we spent a day with Roman numerals or Polish notation or whatever and saw that addition has the same properties. We learned associativity and all those properties in middle school, so there was plenty of time.
– John P
6 hours ago
add a comment |
up vote
12
down vote
which, by the order implied by brackets, should be calculated first
No. It is a common misconception that parentheses have any (general) effect on calculation or evaluation order. They only coerce the parts of your expression into a particular tree, binding the right operands to the right operations for the job.
(And, if you don't use them, this information comes from the "precedence" and associativity of the operators, something that's a result of how the language's syntax tree is defined. In fact, this is still exactly how it works when you use parentheses, but we simplify and say that we're not relying on any precedence rules then.)
Once that's done (i.e. once your code has been parsed into a program) those operands still need to be evaluated, and there are separate rules about how that is done: said rules (as Andrew has shown us) state that the LHS of each operation is evaluated first in Java.
Note that this is not the case in all languages; for example, in C++, unless you're using a short-circuiting operator like &&
or ||
, the evaluation order of operands is generally unspecified and you shouldn't rely on it either way.
Teachers need to stop explaining operator precedence using misleading phrases like "this makes the addition happen first". Given an expression x * y + z
the proper explanation would be "operator precedence makes the addition happen between x * y
and z
, rather than between y
and z
", with no mention of any "order".
1
I wish my teachers had made some separation between the underlying math and the syntax they used to represent it, like if we spent a day with Roman numerals or Polish notation or whatever and saw that addition has the same properties. We learned associativity and all those properties in middle school, so there was plenty of time.
– John P
6 hours ago
add a comment |
up vote
12
down vote
up vote
12
down vote
which, by the order implied by brackets, should be calculated first
No. It is a common misconception that parentheses have any (general) effect on calculation or evaluation order. They only coerce the parts of your expression into a particular tree, binding the right operands to the right operations for the job.
(And, if you don't use them, this information comes from the "precedence" and associativity of the operators, something that's a result of how the language's syntax tree is defined. In fact, this is still exactly how it works when you use parentheses, but we simplify and say that we're not relying on any precedence rules then.)
Once that's done (i.e. once your code has been parsed into a program) those operands still need to be evaluated, and there are separate rules about how that is done: said rules (as Andrew has shown us) state that the LHS of each operation is evaluated first in Java.
Note that this is not the case in all languages; for example, in C++, unless you're using a short-circuiting operator like &&
or ||
, the evaluation order of operands is generally unspecified and you shouldn't rely on it either way.
Teachers need to stop explaining operator precedence using misleading phrases like "this makes the addition happen first". Given an expression x * y + z
the proper explanation would be "operator precedence makes the addition happen between x * y
and z
, rather than between y
and z
", with no mention of any "order".
which, by the order implied by brackets, should be calculated first
No. It is a common misconception that parentheses have any (general) effect on calculation or evaluation order. They only coerce the parts of your expression into a particular tree, binding the right operands to the right operations for the job.
(And, if you don't use them, this information comes from the "precedence" and associativity of the operators, something that's a result of how the language's syntax tree is defined. In fact, this is still exactly how it works when you use parentheses, but we simplify and say that we're not relying on any precedence rules then.)
Once that's done (i.e. once your code has been parsed into a program) those operands still need to be evaluated, and there are separate rules about how that is done: said rules (as Andrew has shown us) state that the LHS of each operation is evaluated first in Java.
Note that this is not the case in all languages; for example, in C++, unless you're using a short-circuiting operator like &&
or ||
, the evaluation order of operands is generally unspecified and you shouldn't rely on it either way.
Teachers need to stop explaining operator precedence using misleading phrases like "this makes the addition happen first". Given an expression x * y + z
the proper explanation would be "operator precedence makes the addition happen between x * y
and z
, rather than between y
and z
", with no mention of any "order".
answered 18 hours ago
Lightness Races in Orbit
281k51453770
281k51453770
1
I wish my teachers had made some separation between the underlying math and the syntax they used to represent it, like if we spent a day with Roman numerals or Polish notation or whatever and saw that addition has the same properties. We learned associativity and all those properties in middle school, so there was plenty of time.
– John P
6 hours ago
add a comment |
1
I wish my teachers had made some separation between the underlying math and the syntax they used to represent it, like if we spent a day with Roman numerals or Polish notation or whatever and saw that addition has the same properties. We learned associativity and all those properties in middle school, so there was plenty of time.
– John P
6 hours ago
1
1
I wish my teachers had made some separation between the underlying math and the syntax they used to represent it, like if we spent a day with Roman numerals or Polish notation or whatever and saw that addition has the same properties. We learned associativity and all those properties in middle school, so there was plenty of time.
– John P
6 hours ago
I wish my teachers had made some separation between the underlying math and the syntax they used to represent it, like if we spent a day with Roman numerals or Polish notation or whatever and saw that addition has the same properties. We learned associativity and all those properties in middle school, so there was plenty of time.
– John P
6 hours ago
add a comment |
up vote
1
down vote
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?
add a comment |
up vote
1
down vote
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?
add a comment |
up vote
1
down vote
up vote
1
down vote
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?
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?
answered yesterday
Michael Puckett II
3,71841436
3,71841436
add a comment |
add a comment |
up vote
1
down vote
It is related to operator precedence and how operators are getting evaluated.
Parentheses '()' has higher precedence and has associativity left to right.
Equality '==' come next in this question and has associativity left to right.
Assignment '=' come last and has associativity right to left.
System use stack to evaluate expression. Expression gets evaluated left to right.
Now comes to original question:
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
First x(1) will be pushed to stack.
then inner (x = y) will be evaluated and pushed to stack with value x(3).
Now x(1) will be compared against x(3) so result is false.
x = 1; // reset
System.out.println((x = y) == x); // true
Here,
(x = y) will be evaluated, now x value become 3 and x(3) will be pushed to stack.
Now x(3) with changed value after equality will be pushed to stack.
Now expression will be evaluated and both will be same so result is true.
New contributor
2
"Assignment '=' come last and evaluated right to left." That's incorrect, or misleading. Assignments are right-to-left associative, which affects grouping in larger expressions, but their operands are evaluated left-to-right. Also see this answer and Precedence vs Associativity vs Order by Eric Lippert. Precedence isn't whyx==(x=y)
and(x=y)==x
have different results.
– Radiodef
9 hours ago
@Radiodef, You are correct, updated my answer.
– Amit
1 hour ago
add a comment |
up vote
1
down vote
It is related to operator precedence and how operators are getting evaluated.
Parentheses '()' has higher precedence and has associativity left to right.
Equality '==' come next in this question and has associativity left to right.
Assignment '=' come last and has associativity right to left.
System use stack to evaluate expression. Expression gets evaluated left to right.
Now comes to original question:
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
First x(1) will be pushed to stack.
then inner (x = y) will be evaluated and pushed to stack with value x(3).
Now x(1) will be compared against x(3) so result is false.
x = 1; // reset
System.out.println((x = y) == x); // true
Here,
(x = y) will be evaluated, now x value become 3 and x(3) will be pushed to stack.
Now x(3) with changed value after equality will be pushed to stack.
Now expression will be evaluated and both will be same so result is true.
New contributor
2
"Assignment '=' come last and evaluated right to left." That's incorrect, or misleading. Assignments are right-to-left associative, which affects grouping in larger expressions, but their operands are evaluated left-to-right. Also see this answer and Precedence vs Associativity vs Order by Eric Lippert. Precedence isn't whyx==(x=y)
and(x=y)==x
have different results.
– Radiodef
9 hours ago
@Radiodef, You are correct, updated my answer.
– Amit
1 hour ago
add a comment |
up vote
1
down vote
up vote
1
down vote
It is related to operator precedence and how operators are getting evaluated.
Parentheses '()' has higher precedence and has associativity left to right.
Equality '==' come next in this question and has associativity left to right.
Assignment '=' come last and has associativity right to left.
System use stack to evaluate expression. Expression gets evaluated left to right.
Now comes to original question:
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
First x(1) will be pushed to stack.
then inner (x = y) will be evaluated and pushed to stack with value x(3).
Now x(1) will be compared against x(3) so result is false.
x = 1; // reset
System.out.println((x = y) == x); // true
Here,
(x = y) will be evaluated, now x value become 3 and x(3) will be pushed to stack.
Now x(3) with changed value after equality will be pushed to stack.
Now expression will be evaluated and both will be same so result is true.
New contributor
It is related to operator precedence and how operators are getting evaluated.
Parentheses '()' has higher precedence and has associativity left to right.
Equality '==' come next in this question and has associativity left to right.
Assignment '=' come last and has associativity right to left.
System use stack to evaluate expression. Expression gets evaluated left to right.
Now comes to original question:
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
First x(1) will be pushed to stack.
then inner (x = y) will be evaluated and pushed to stack with value x(3).
Now x(1) will be compared against x(3) so result is false.
x = 1; // reset
System.out.println((x = y) == x); // true
Here,
(x = y) will be evaluated, now x value become 3 and x(3) will be pushed to stack.
Now x(3) with changed value after equality will be pushed to stack.
Now expression will be evaluated and both will be same so result is true.
New contributor
edited 1 hour ago
New contributor
answered 17 hours ago
Amit
4114
4114
New contributor
New contributor
2
"Assignment '=' come last and evaluated right to left." That's incorrect, or misleading. Assignments are right-to-left associative, which affects grouping in larger expressions, but their operands are evaluated left-to-right. Also see this answer and Precedence vs Associativity vs Order by Eric Lippert. Precedence isn't whyx==(x=y)
and(x=y)==x
have different results.
– Radiodef
9 hours ago
@Radiodef, You are correct, updated my answer.
– Amit
1 hour ago
add a comment |
2
"Assignment '=' come last and evaluated right to left." That's incorrect, or misleading. Assignments are right-to-left associative, which affects grouping in larger expressions, but their operands are evaluated left-to-right. Also see this answer and Precedence vs Associativity vs Order by Eric Lippert. Precedence isn't whyx==(x=y)
and(x=y)==x
have different results.
– Radiodef
9 hours ago
@Radiodef, You are correct, updated my answer.
– Amit
1 hour ago
2
2
"Assignment '=' come last and evaluated right to left." That's incorrect, or misleading. Assignments are right-to-left associative, which affects grouping in larger expressions, but their operands are evaluated left-to-right. Also see this answer and Precedence vs Associativity vs Order by Eric Lippert. Precedence isn't why
x==(x=y)
and (x=y)==x
have different results.– Radiodef
9 hours ago
"Assignment '=' come last and evaluated right to left." That's incorrect, or misleading. Assignments are right-to-left associative, which affects grouping in larger expressions, but their operands are evaluated left-to-right. Also see this answer and Precedence vs Associativity vs Order by Eric Lippert. Precedence isn't why
x==(x=y)
and (x=y)==x
have different results.– Radiodef
9 hours ago
@Radiodef, You are correct, updated my answer.
– Amit
1 hour ago
@Radiodef, You are correct, updated my answer.
– Amit
1 hour ago
add a comment |
up vote
0
down vote
It is not the same. The left hand side will always be evaluated before the right hand side, and the brackets don't specify an order of execution, but a grouping of commands.
With:
x == (x = y)
You are basically doing the same as:
x == y
And x will have the value of y after the comparison.
While with:
(x = y) == x
You are basically doing the same as:
x == x
After x took y's value. And it will always return true.
add a comment |
up vote
0
down vote
It is not the same. The left hand side will always be evaluated before the right hand side, and the brackets don't specify an order of execution, but a grouping of commands.
With:
x == (x = y)
You are basically doing the same as:
x == y
And x will have the value of y after the comparison.
While with:
(x = y) == x
You are basically doing the same as:
x == x
After x took y's value. And it will always return true.
add a comment |
up vote
0
down vote
up vote
0
down vote
It is not the same. The left hand side will always be evaluated before the right hand side, and the brackets don't specify an order of execution, but a grouping of commands.
With:
x == (x = y)
You are basically doing the same as:
x == y
And x will have the value of y after the comparison.
While with:
(x = y) == x
You are basically doing the same as:
x == x
After x took y's value. And it will always return true.
It is not the same. The left hand side will always be evaluated before the right hand side, and the brackets don't specify an order of execution, but a grouping of commands.
With:
x == (x = y)
You are basically doing the same as:
x == y
And x will have the value of y after the comparison.
While with:
(x = y) == x
You are basically doing the same as:
x == x
After x took y's value. And it will always return true.
edited 9 hours ago
answered 9 hours ago
Or10n
134213
134213
add a comment |
add a comment |
up vote
0
down vote
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
New contributor
add a comment |
up vote
0
down vote
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
New contributor
add a comment |
up vote
0
down vote
up vote
0
down vote
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
New contributor
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
New contributor
New contributor
answered 4 hours ago
Ahmad Bedirxan
1
1
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53749841%2fwhy-is-x-x-y-not-the-same-as-x-y-x%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
38
The left hand side is always evaluated before the right hand side. The brackets don't make a difference to that.
– Louis Wasserman
yesterday
6
Evaluating the expression
x = y
is certainly relevant, and causes the side effect thatx
is set to the value ofy
.– Louis Wasserman
yesterday
22
Do yourself and your teammates a favor and don't mix state mutation into the same line as state examination. Doing so drastically reduces the readability of your code. (There are some cases where it's absolutely necessary because of atomicity requirements, but functions for those already exist and their purpose would be instantly recognized.)
– jpmc26
yesterday
20
The real question is why you want to write code like this.
– Broman
yesterday
9
The key to your question is your false belief that parentheses imply evaluation order. That is a common belief because of how we're taught math in elementary school and because some beginner programming books still get it wrong, but it is a false belief. This is a pretty frequent question. You might benefit from reading my articles on the subject; they are about C# but they apply to Java: ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order ericlippert.com/2009/08/10/precedence-vs-order-redux
– Eric Lippert
15 hours ago