Java 仕様(Java 7 仕様) によると、セクション 15.26.2 (529 ページ)。
の形式の複合代入式E1 op= E2
は と同等ですE1 = (T) ((E1) op (E2))
。ここで、T
は の型ですがE1
、E1
は 1 回だけ評価されます。
セクション 15.7 評価順序(ページ 423)によると(強調鉱山):
15.7 評価順序
Java プログラミング言語は、演算子のオペランドが特定の評価順序 (つまり、左から右) で評価されるように見えることを保証します。
15.7.1 左側のオペランドを最初に評価する
二項演算子の左側のオペランドは、右側のオペランドの一部が評価される前に完全に評価されているように見えます。
演算子が複合代入演算子 (§15.26.2) である場合、左側のオペランドの評価には、左側のオペランドが示す変数の記憶と、暗黙の 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