Во время изучения порядка вычисления выражений java я столкнулся с одним явлением, которое не могу четко объяснить себе. Есть два вопроса викторины. Требуется определить вывод консоли.
Пример 1
int[] a = {5, 5};
int b = 1;
a[b] = b = 0;
System.out.println(Arrays.toString(a));
Правильный вывод консоли: [5,0]
Пример 2
public class MainClass {
static int f1(int i) {
System.out.print(i + ",");
return 0;
}
public static void main(String[] args) {
int i = 0;
i = i++ + f1(i);
System.out.print(i);
}
}
Правильный вывод консоли: 1,0
Как я узнал, в java есть группы операторов (уровни) с упорядоченным приоритетом, а выражения оцениваются согласно на приоритет оператора. Также существует ассоциативность каждой группы, и если операторы имеют одинаковый приоритет, то они оцениваются в порядке, указанном ассоциативностью группы. Таблица приоритетов операторов (от Cay S. Horstmann - Core Java V.1):
<b>#<b> operator</b> associativity</b>
1 [] . () <i>method call</i> left to right
2 ! ~ ++ -- + - (type) <i>cast</i> new right to left
3 * / % left to right
4 + - left to right
...
14 = += -= <i>the rest are omitted</i> right to left
Из таблицы выше становится ясно, что в примере 1 оператор с наивысшим приоритетом - индексирование массива a[b]
и затем операторы присвоения оцениваются справа налево: b=0
, затем a[1]=0
. Вот почему a=[5,0]
.
Но пример 2 смущает меня. Согласно таблице приоритетов, оператор с наивысшим приоритетом - это f1(i)
вызов метода (, который должен вывести 0
), затем унарный постинкремент i++
(который использует текущий i=0
и увеличивает его после), затем оператор сложения 0+0
и оператор присвоения наконец i=0
. Итак, я предположил, что правильный вывод 0,0
.
Но на самом деле это не так. Фактически сначала вычисляется унарный постинкремент i++
( увеличивается i
до 1
), затем вызывается метод f1(i)
печатает 1
и возвращает 0
и, наконец, оператор присваивания назначает i=0+0
, поэтому окончательное значение i
равно 0
, а правильный ответ 1,0
.
Полагаю, это так из-за ассоциативности двоичного оператора сложения "слева направо", но в этом случае, почему сложение вычисляется первым в примере 2, а в примере 1 оператор наивысшего приоритета a[b]
рассчитывается первым? Я заметил, что все операторы в примере 2 находятся в разных группах, поэтому мы не должны вообще принимать во внимание ассоциативность операторов, не так ли? Разве мы не должны просто упорядочить все операторы из примера 2 по приоритету и оценить его в результирующем порядке?