Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary operator, syntax error when using assignment

The following 3 lines of code below compile OK. (Please note that this code is an example of "artificial Java coding", and consequently wouldn't be seen in professionally written code.)

int x, y; boolean b=true;  x = b ? y=1 : 2;  // Compiles OK. 

If I now change the code in line #3 above, so that it looks like the following code line below, the compiler generates an error.

// Change the position of the "y assignment", and now the code doesn't compile. x = b ? 1 : y=2;   

Here is the syntax error message:

Ternary operator syntax error

Can someone please explain this behaviour (to a rookie Java learner)? Thank you.

like image 475
user2911290 Avatar asked Dec 05 '13 12:12

user2911290


2 Answers

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 means a=(b=c), which assigns the value of c to b and then assigns the value of b to a.

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).

like image 75
Martijn Courteaux Avatar answered Sep 25 '22 15:09

Martijn Courteaux


See "Java operator precedence". Meanwhile, use:

x = (b ? 1 : (y=2));  
like image 41
helb Avatar answered Sep 25 '22 15:09

helb