Ответ 1
Согласно спецификация Java (спецификация Java 7), раздел 15.26.2 (стр. 529).
Совокупное выражение выражения формы
E1 op= E2
эквивалентноE1 = (T) ((E1) op (E2))
, гдеT
- типE1
, за исключением того, чтоE1
оценивается только один раз.
В соответствии с разделом 15.7 "Порядок оценки" (Страница 423) (emphasis):
15.7 Порядок оценки
Язык программирования Java гарантирует, что операнды операторов будут оцениваться в определенном порядке оценки, а именно слева направо.
15.7.1 Оценить первый операнд левой руки
Левый операнд двоичного оператора оказывается полностью оцененным до того, как будет оценена любая часть правого операнда.
Если оператор является оператором составного присваивания (§15.26.2), то оценка левого операнда включает в себя как запоминание переменной, которую левый операнд обозначает, так и выборку и сохранение этого значения переменной для использовать в подразумеваемой двоичной операции.
Если оценка левого операнда двоичного оператора завершается внезапно, никакая часть правого операнда, по-видимому, не была оценена.
Более подробно описано в разделе 15.26.2 (стр. 529):
Если выражение левого операнда не является выражением доступа к массиву, то:
• Во-первых, левый операнд оценивается для создания переменной. [Обрезается]
• В противном случае значение левого операнда сохраняется, а затем оценивается правый операнд. [Обрезается]
• В противном случае сохраненное значение левой переменной и значение правого операнда используются для выполнения двоичной операции, указанной оператором составного присваивания. [Обрезается]
• В противном случае результат двоичной операции преобразуется в тип левой переменной, подвергается преобразованию набора значений (п. 5.1.13) в соответствующее стандартное значение (не заданное значение расширенного показателя), и результат преобразования сохраняется в переменной.
Пример в документации
Пример 15.26.2-2. Значение левой части составного задания сохраняется до оценки правой стороны.
class Test { public static void main(String[] args) { int k = 1; int[] a = { 1 }; k += (k = 4) * (k + 2); a[0] += (a[0] = 4) * (a[0] + 2); System.out.println("k==" + k + " and a[0]==" + a[0]); } }
Итак, выражение в вопросе переписано и сгруппировано как:
i = i ^ (j = j ^ (i = i ^ j));
Левые операнды оцениваются:
i = 24 ^ (j = 17 ^ (i = 24 ^ 17));
**
Так как значение i
не обновляется, как ожидалось, это приведет к тому, что значение i
получит 0, когда 24
будет заменено на j
.