В Java, почему присваивание в скобках не происходит до того, как вычисляется остальная часть выражения?
Рассмотрим
int a = 20;
a = a + (a = 5); // a == 25, why not 10?
Разве скобки не превосходят все правила приоритета? Являются ли некоторые переменные на RHS предварительно заполненными до оценки определенных выражений?
3 ответов:
Потому что
aзагружается первым в вашем примере, а затем вычисляется бит в скобках. Если вы поменяли порядок:int a = 20; a = (a = 5) + a; System.out.println(a);10... вы действительно получаете 10. Выражения вычисляются слева направо.
Рассмотрим это:
f() + g()
fбудет вызван раньшеg. Представьте себе, насколько это было бы неинтуитивно, вf() + (g())Иметь
gбыть вызванным доf.Все это подробно описано в JLS §15.7.1 (спасибо @paisanco за то, что поднял его в комментариях).
Из JLS
Язык программирования Java гарантирует, что операнды операторы, по-видимому, оцениваются в определенном порядке оценки, а именно, слева направо.
И
Левый операнд двоичного оператора представляется полностью вычисляется перед вычислением любой части правого операнда.
Обертывание выражения в скобки просто помогает группировке (и ассоциативности), это не заставляет его оценка должна произойти до того, как что-нибудь произойдет слева от него.
Сгенерированный байт-код:
BIPUSH 20 ISTORE 1 ILOAD 1 ICONST_5 DUP ISTORE 1 IADD ISTORE 1 RETURN LOCALVARIABLE a IСначала вы присваиваете 20 первой переменной (a):
BIPUSH 20 ISTORE 1Затем вы загружаете содержимое первой переменной в стек (20 помещается в стек):
ILOAD 1Затем вы дважды нажимаете константу '5' в стек (20 5 5):
ICONST_5 DUPЗатем вы сохраняете верхнюю часть стека в первую переменную (a):
ISTORE 1А теперь 5, стек теперь (20 5). Мы добавляем оба операнда и помещаем их сумму в первую переменную (a):
IADD ISTORE 1В качестве следовательно, а теперь 20 + 5 = 25. Мы заканчиваем:
RETURN
Comments