Это связано с оценкой операндов перед порядком операторов (приоритет).
Перед выполнением операторов оцениваются операнды, которые в Java всегда выполняются в порядке слева направо.
Самый левый A
оценивается как 5
, затем самый левый B
равен 2
, затем второй A
равен 5
, а второй B
также равен 2
. Эти значения сохраняются для последующего расчета.
JLS, раздел 15.26. 2, описывает процедуру вычисления составного оператора присваивания.
Если выражение левого операнда не является выражением доступа к массиву, то:
Сначала оценивается левый операнд для создания переменной. Если это вычисление завершается внезапно, то и выражение присваивания завершается внезапно по той же причине; правый операнд не оценивается, и присваивание не происходит.
В противном случае значение левого операнда сохраняется, а затем оценивается правый операнд. Если это вычисление завершается внезапно, выражение присваивания завершается внезапно по той же причине, и присваивание не происходит.
В противном случае сохраненное значение левой переменной и значение правого операнда используются для выполнения бинарной операции, указанной составным оператором присваивания. Если эта операция завершается внезапно, выражение присваивания завершается внезапно по той же причине, и присваивание не происходит.
В противном случае результат бинарной операции преобразуется в тип левой переменной, подвергается преобразованию набора значений (§5.1.13) в соответствующий стандартный набор значений (не набор значений с расширенным показателем степени), а результат преобразования сохраняется в переменной.
(выделено мной)
Затем выполняются операторы, причем *=
имеет правую ассоциативность. Это означает, что операция выполняется справа налево. Крайний правый A *= B
выполняется, присваивая 10
A
. Выполняется средний B *= A
, присваивая 20
B
. Однако при выполнении самого левого A *= B
сохраняется сохраненное значение A
— 5
. При умножении на 20
100
присваивается A
.
A *= B*= A *= B; // A is now 100
Если мы разобьем это на 3 оператора, то вы получите ожидаемое 200
, потому что A
будет снова оцениваться как часть последнего оператора как 10
, а не 5
, потому что сохраненное значение для A
теперь равно 10
.
A *= B;
B *= A;
A *= B; // A is now 200
person
rgettman
schedule
22.08.2019
A *=
использует исходное значениеA
, а не результат более поздних операций - person user85421   schedule 23.08.2019