i++ と ++i の違い
評価される値のタイミングが違います。i = i++ が何も変えない理由も解説します。
なぜエラーが出ないのか
出力: 0
(エラーなし)- javacは何も報告しません。文法として正しいためです
出力: 0- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 public class Main { 2 public static void main(String[] args) { 3 int i = 0; 4 System.out.println(i++ ); ^ 5 } 6 }
出力: 0期待: 1 (コンパイルは通っています)
i++ は インクリメント前の値を返します。先に増やしてから使うなら ++i です。
直し方: i++ を ++i にします。
広告
広告スロット(未設定)
パターン2
1 public class Main { 2 public static void main(String[] args) { 3 int i = 5; 4 i = i++ ; ^ 5 System.out.println(i); 6 } 7 }
出力: 5期待: 6 (コンパイルは通っています)
i = i++ は元の値を代入し直すため何も変わりません。自己代入とインクリメントを混ぜないのが安全です。
直し方: i++ を i + 1 にします。
パターン3
1 public class Main { 2 public static void main(String[] args) { 3 int i = 0, count = 0; 4 while (++i < 3) { ^ 5 count++; 6 } 7 System.out.println(count); 8 } 9 }
出力: 2期待: 3 (コンパイルは通っています)
++iは先に増やしてから比較するため、判定に使われる値が1つ多く進みます。ループ回数が意図より1回少なくなります。
直し方: ++i を i++ にします。
パターン4
1 public class Main { 2 public static void main(String[] args) { 3 int i = 0, sum = 0; 4 for (int k = 0; k < 3; k++) { 5 sum += ++i ; ^ 6 } 7 System.out.println(sum); 8 } 9 }
出力: 6期待: 3 (コンパイルは通っています)
++iだと足す前にiが増えるため、0,1,2ではなく1,2,3を合計してしまいます。
直し方: ++i を i++ にします。
パターン5
1 public class Main { 2 public static void main(String[] args) { 3 int[] scores = {10, 20, 30}; 4 int i = 0; 5 System.out.println(scores[++i ] + "," + scores[i]); ^ 6 } 7 }
出力: 20,20期待: 10,20 (コンパイルは通っています)
++iは参照の前にiを増やすため、1回目と2回目の参照が同じ添字を指してしまいます。
直し方: ++i を i++ にします。
よくある誤解
ループの i++ と ++i は結果が同じです。違いが出るのは、その値を使うときだけです。
実務での勘所
i = i++;がなぜ何も変えないのかは、評価の手順を分解すると分かります。i++は「今のiの値を(あとで代入に使うため)覚えておいてから、iをインクリメントする」という順で動きます。その後の代入は、インクリメント後の新しい値ではなく最初に覚えておいた古い値をiに書き戻すため、結果的にインクリメントが上書きで消えます。Javaはこの評価順序を仕様で厳密に定めていますが、GoogleのJavaスタイルガイドなど多くの実務の規約は、同じ変数を1つの式の中で++と一緒に他の目的でも使うこと自体を禁止しています。