では、先ほどの「x = x++;」に続いて、x = ++x; のJVMレベルでの挙動を見ていきましょう。両者を比較すると理解が深まります。
1. ソースコード
public class Sample {
public static void main(String[] args) {
int x = 0;
x = ++x;
System.out.println(x);
}
}
Java2. コンパイル後のバイトコード(javap -c Sample の一部)
0: iconst_0 // 定数0をスタックに積む
1: istore_1 // x = 0 をローカル変数1に格納
2: iinc 1, 1 // ローカル変数1 (x) をインクリメント(x=1になる)
5: iload_1 // xの値(1)をスタックに積む
6: istore_1 // スタックトップの値(1)をxに代入 → x=1
7: getstatic ...
10: iload_1
11: invokevirtual ...
3. スタックとローカル変数の動き
- ステップ 2 (
iinc 1, 1)
ローカル変数xを直接インクリメント。
→ ローカル変数: x=1 - ステップ 5 (
iload_1)
xの値(1)をスタックに積む。
→ スタック: [1], ローカル変数: x=1 - ステップ 6 (
istore_1)
スタックトップの値(1)をローカル変数xに格納。
→ スタック: [], ローカル変数: x=1
結果として、インクリメントされた値がそのまま代入されるため、x は1に更新されます。
4. x = x++; との違い
| 式 | バイトコードの流れ | 最終的なxの値 |
|---|---|---|
x = x++; | スタックに古い値を積む → ローカル変数を+1 → スタックの古い値を再代入 | 変化しない(元の値のまま) |
x = ++x; | 先にローカル変数を+1 → その新しい値をスタックに積む → 代入 | インクリメントされた値になる |
5. まとめ
x = x++;→ 無意味なコード(結果的にxは変わらない)x = ++x;→ xが1増える(普通に++x;と同じ効果)- 違いは「スタックに積むタイミング」と「インクリメントの順序」によるもの。
👉 ここまでで「JVMレベルでの動き」が見えたと思います。
もしさらに深掘りしたいなら、javap -v で実際の定数プールや局所変数テーブルを確認すると、より低レベルな理解ができます。
