Почему такой приоритет операций в Java
int number = 2;
System.out.println(number + number * (number + ++number));
System.out.println(number);
Почему на экран будет выведено 12, а не 18. Немного не понимаю, number же увеличивается в скобках. Почему еще у унарных операторов ассоциативность справа налево? Как это работает?
Ответы (1 шт):
Есть три вещи, которые важно не путать:
- приоритет операций
- ассоциативность операций
- порядок вычисления подвыражений
Рассмотрим на примере выражения a / b / c - d.
Приоритет и ассоциативность задают правила расстановок скобок в выражении. Т.е. приоритет операций нам говорит, что a / b / c - d == (a / b / c) - d. Ассоциативность - что (a / b / c) - d == ((a / b) / c) - d.
Обратите внимание, что правила ассоциативности и приоритета ничего не говорят нам о том, в каком порядке нужно вычислять подвыражения a, b, c и d. Они говорят только о том, в каком порядке нужно выполнять операции над операндами, но не о порядке вычисления операндов.
А об этом говорит правило порядка вычисления подвыражений:
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
Весь ваш вопрос и замешательство связаны как раз с порядком вычисления подвыражений.
Для выражения number + number * (number + ++number) порядок вычислений подвыражений будет таким:
number + number * (number + ++number)
^ ^ ^ ^
| | | |
1 2 3 4 - порядок вычисления
2 + 2 * ( 2 + 3 ) == 12
Теперь, что касается a = 3; b = ++a + (a-- * ++a);. Тут к написанному выше еще добавляется правило, что пре-(пост-) ин(де)кремент модифицирует переменную до(после) вычисления подвыражения.
a = 3;
b = ++a + (a-- * ++a);
^ ^ ^
1 2 3 порядок вычисления подвыражений
4 + (4 * 4) значение подвыражения
4 3 4 значение а после вычисления подвыражения
Так что в результате будет 4 * (4 + 4).
Почему еще у унарных операторов ассоциативность справа налево? Как это работает?
В выражениях типа ++ ++ a и - - 2 скобки согласно ассоциативности расставляются так (++ (++ a)) и (- (- 2)), что ожидаемо и естественно, т.к. мы не можем применять оператор до того, как рассчитаем его аргумент.