Тернарный оператор, синтаксическая ошибка при использовании присваивания
следующие 3 строки кода ниже компилируют OK. (Обратите внимание, что этот код является примером "искусственного кодирования Java" и, следовательно, не будет отображаться в профессионально написанном коде.)
int x, y;
boolean b=true;
x = b ? y=1 : 2; // Compiles OK.
Если я теперь изменю код в строке #3 выше, чтобы он выглядел как следующая строка кода ниже, компилятор генерирует ошибку.
// Change the position of the "y assignment", and now the code doesn't compile.
x = b ? 1 : y=2;
вот сообщение об ошибке синтаксиса:
может кто-нибудь объяснить это поведение (для новичка Java learner)? Спасибо.
4 ответов
Short:
это из-за приоритета операторов. Первый случай равен этому:
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
tob
и затем присваивает значениеb
toa
.результат первого операнда оператора присваивания должна быть переменная, или ошибка времени компиляции происходит. (это объясняет ошибку времени компиляции, с которой вы сталкиваетесь)
во время выполнения, результат выражение присваивания - это значение переменной после того, как присвоение произошло. Результат выражения присваивания сам по себе не является переменной.
применение правой ассоциативности:
x = ((b ? 1 : y) = 2);
наконец, мы можем понять, почему это создает ошибку компилятора: результат троичного условного оператора не переменная (который на самом деле не находится в JLS, насколько я могу найти, однако компилятор говорит вам в простом тестовом примере, таком как этот: https://ideone.com/kMr7Xv).
приоритет оператора Java выглядит следующим образом
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
здесь ternary
перед assignment
операции. таким образом, ваше заявление будет таким
x= (троичная оценка) = значение присваивания
если вы все еще хотите установить значение для y, когда b равно false, вы можете использовать ()
для 'y=2' принесите внутри тройную оценку.
x = b ? 1 : (y=2);