Как оценивается A *= B *= A *= B?

public static void main(String[] args) {
    int A=5;
    int B=2;

    A *= B*= A *= B ;

    System.out.println(A);
    System.out.println(B);
}

Когда я рассчитал эту проблему на бумаге, я нашел A=200 B=20, но когда я записал ее в eclipse, она показывает A=100 B=20

Можете ли вы объяснить решение, как решение на бумаге?

Пробовал решать в Eclipse и сам.

Как это решить?


person tarikyaylagul    schedule 22.08.2019    source источник
comment
первый A *= использует исходное значение A, а не результат более поздних операций   -  person user85421    schedule 23.08.2019
comment
Тесно связано: Почему "a^=b^=a^=b;" отличается от «a^=b; б^=а; а^=б;”?   -  person Ivar    schedule 23.08.2019
comment
Задания оцениваются справа налево.   -  person user207421    schedule 23.08.2019


Ответы (2)


Начиная с A=5, B=2

A становится A * B * A * B, что равно 100, а B становится B * A * B, что равно 20.


Более детально:

A *= B *= A *= B

is

A = A * (B = B * (A = A * B)) 

Это решает

A = 5 * (B = 2 * (A = 5 * 2))

что значит

A = 5 * (B = 2 * (A = 10)) // set A to 10
A = 5 * (B = 2 * 10)
A = 5 * (B = 20) // set B to 20
A = 5 * 20
A = 100 // set A to 100
person khelwood    schedule 22.08.2019

Это связано с оценкой операндов перед порядком операторов (приоритет).

Перед выполнением операторов оцениваются операнды, которые в 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 сохраняется сохраненное значение A5. При умножении на 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