Short:
This is because of operator precedence. The first case is equal to this:
x = (b ? (y=1) : 2); // Compiles OK.
While the second is:
x = (b ? 1 : y) = 2;
The first one compiles indeed fine, because an assignment gets evaluated to the new value. So, if b
is true, it will cause to be both x
and y
equal to 1. The second one is like saying: x = 1 = 2
. So, yes, to fix this compiler error, add paratheses to your statement:
x = (b ? 1 : (y = 2)); // Outer () are not needed, but is clearer, IMHO.
Longer:
First of all, operator precedence in Java says that the assignment operators have lower priority than the conditional ternary operator. This means that your second expression is equivalent to:
x = (b ? 1 : y) = 2;
As you can see, this looks plain wrong. Indeed, JLS §15.26 says this:
There are 12 assignment operators; all are syntactically right-associative (they group right-to-left). Thus,
a=b=c
meansa=(b=c)
, which assigns the value ofc
tob
and then assigns the value ofb
toa
.The result of the first operand of an assignment operator must be a variable, or a compile-time error occurs. (This explains the compile time error you face)
At run time, the result of the assignment expression is the value of the variable after the assignment has occurred. The result of an assignment expression is not itself a variable.
Applying right-associativity:
x = ((b ? 1 : y) = 2);
Finally we can see why this generates a compiler error: the result of a ternary conditional operator is not a variable (which is actually not in the JLS as far as I can find, however the compiler tells you in a simple test case like this one: https://ideone.com/kMr7Xv).