Ответ 1
Короткие
Это связано с приоритетом оператора. Первый случай равен этому:
x = (b ? (y=1) : 2); // Compiles OK.
Пока второе:
x = (b ? 1 : y) = 2;
Первый компилируется действительно отлично, потому что присваивание получает новое значение. Таким образом, если b
истинно, это приведет к тому, что оба значения x
и y
равны 1. Второе похоже на высказывание: x = 1 = 2
. Итак, да, чтобы исправить эту ошибку компилятора, добавьте paratheses в ваш оператор:
x = (b ? 1 : (y = 2)); // Outer () are not needed, but is clearer, IMHO.
Более длинные:
Прежде всего, приоритет оператора в Java говорит, что операторы присваивания имеют более низкий приоритет, чем условный тернарный оператор. Это означает, что ваше второе выражение эквивалентно:
x = (b ? 1 : y) = 2;
Как вы можете видеть, это выглядит неправильно. Действительно, JLS §15.26 говорит следующее:
Существует 12 операторов присваивания; все синтаксически право-ассоциативный (они группируются справа налево). Таким образом,
a=b=c
означаетa=(b=c)
, который присваивает значениеc
b
, а затем присваивает значениеb
a
.Результатом первого операнда оператора присваивания должна быть переменная, или возникает ошибка времени компиляции. (Это объясняет ошибку времени компиляции)
Во время выполнения результатом выражения присваивания является значение переменной после того, как произошло присвоение. Результат выражения присваивания сам по себе не является переменной.
Применение правой ассоциативности:
x = ((b ? 1 : y) = 2);
Наконец, мы можем понять, почему это порождает ошибку компилятора: результат тернарного условного оператора не является переменной (которая на самом деле не находится в JLS, насколько я могу найти, однако компилятор говорит вам в простом примере теста как этот: https://ideone.com/kMr7Xv).