28

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.

5
  • 5
    Very interesting. This might make a good interview question. Commented Dec 5, 2013 at 12:29
  • 2
    For anyone curious, it looks like both syntaxes are valid in C#. Commented Dec 5, 2013 at 16:44
  • Minor note: If b is true, then y is assigned 1. But if b is false, then this assignment isn't executed, and y retains its existing value. Commented Dec 5, 2013 at 18:09
  • 1
    @Duncan Really? Would you like to see such question on interview? Do you think that knowing precedence of every single operator in Java is required to be Java developer? From top of your head would you be able to tell me if this compiles correctly: if (obj instanceof obj==null ? String.class : Integer.class) and how does it work? Commented Dec 5, 2013 at 22:54
  • 1
    @Pshemo I like questions that provoke thought and debate. Sure, I'd be very impressed if the candidate knew the answer immediately, but I'd not expect that. Instead, I'd prefer to see how they went about solving the issue; what ideas they had and to see if they got there with further information provided from me. Commented Dec 6, 2013 at 8:12

4 Answers 4

37

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

Sign up to request clarification or add additional context in comments.

4 Comments

@guido For which expression do you believe that to be true? It's not true for x = (b ? (y=1) : 2);.
@Duncan: I don't know what happend. It's probably a bug in StackOverflow. Our responses to this commented were deleted automagically. Guido removed his statement but came automagically back... In my comment I included this demo: ideone.com/X3ezxq
@Martijn Corteaux i did delete my answer (because yours came a couple of minutes first ans is better); my comment is still here but it is wrong.
@MartijnCourteaux A glitch in the Matrix.
4

See "Java operator precedence". Meanwhile, use:

x = (b ? 1 : (y=2)); 

Comments

3

Java operator precedence is as follows

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

here ternary comes before assignment operation. so your statement will be like this

x= ( ternary evaluation )= assignment value

if you still want set value for y , when b is false, you may use () for 'y=2' bring inside ternary evaluation.

x = b ? 1 : (y=2);

Comments

2

Brother, try putting expressions in brackets.

X= (b? 1 : (y=2));

this will work fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.