デクリメントの全体像
デクリメントは「数値を 1 減らす」最短記法で、-- を使います。Java では「前置(--n)」と「後置(n--)」があり、式として使ったときの結果が異なります。対象は数値プリミティブ(byte, short, int, long, char, float, double)で、boolean には使えません。配列の逆順走査、残回数のカウントダウン、インデックス調整などで多用されます。
前置と後置の違い
基本形と直感的な使い分け
int n = 5;
System.out.println(--n); // 4(前置:先に減らしてから使う)
System.out.println(n--); // 4(後置:使ってから減る。n は 3 になる)
System.out.println(n); // 3
Java前置は「その場で 1 減って、その減った値が式の結果」になります。後置は「その場では元の値を返し、評価後に変数だけ 1 減る」動きです。式中で使うと読み手が混乱するため、初心者は「単独の行」や「ループの更新部」に限定すると安全です。
よくある落とし穴(重要ポイントの深掘り)
代入と後置のトラップ
int x = 3;
x = x--; // x は 3 のまま(後置は「元の値」を返す)
System.out.println(x); // 3
Javax-- は「元の値を返したあと減る」ため、x = x--; は結果として減りません。値を減らしたいだけなら、代入と混ぜずに x--; を単独で書きます。
同じ式で複数回の増減
int i = 3;
int r = i-- + --i; // 評価順序は規定されているが、読み手には難解
Java同じ変数に複数の -- を同じ式内で使うと、可読性が極端に落ちます。必ず分解して段階的に書きましょう。
配列アクセスと後置の組み合わせ
int[] a = {10, 20, 30};
int i = 2;
System.out.println(a[i--]); // 30 を表示し、i は 1 になる
System.out.println(a[i]); // 20
Java便利ですが、条件や複雑な計算と混ぜると誤読の原因になります。「先に減らす→アクセス」を分けると安全です。
ループとカウンタでの使い方
逆順走査の定番パターン
int[] arr = {3, 8, 2, 7};
for (int i = arr.length - 1; i >= 0; i--) {
System.out.println(arr[i]);
}
Javai-- と --i は更新部では同じ効果です(式の結果を使わないため)。逆順走査では「開始値と終了条件(i >= 0)」を明示して境界を外さないようにします。
while ループでのカウントダウン
int remain = 3;
while (remain > 0) {
System.out.println("remain=" + remain);
--remain; // 単独使用なら前置・後置どちらでも同じ
}
Java単独行で使う限り、前置と後置の違いは気にする必要がありません。式へ混ぜないのがコツです。
数値型ごとの挙動と境界(重要ポイントの深掘り)
short/byte/char に対する —
short s = 1;
s--; // OK(暗黙キャストで元の型に戻る)
/* s = s - 1; */ // NG:中間結果が int になり、short に戻せない
char c = 'B';
c--; // 'A' になる(コード値が 1 減る)
Java-- は暗黙に「元の型へ戻す」ため、short/byte/char でも使えます。一方 s = s - 1; は中間結果が int になるためコンパイルエラーです。計算が増えるなら、最初から int に統一すると安全です。
オーバーフロー(アンダーフロー)と浮動小数点
int min = Integer.MIN_VALUE;
min--; // 2147483647(循環。例外は出ない)
Java整数は範囲外に出ても例外にならず循環します。大きく減る可能性があるなら long を使う、または更新前後で境界チェックを入れます。float/double への -- も可能ですが、連続減算は誤差や意図の不明瞭さにつながることがあるため、-= 1 の方が読みやすい場合があります。
デクリメントの代替表記と可読性
-= 1 を使って意図を明確に
int i = 5;
i -= 1; // i-- と同じ効果だが、演算の意味が明確
Java式としての戻り値が不要で、単に 1 減らしたいだけなら -= 1 は誤解が少なくなります。チーム規約や文脈に合わせて選びましょう。
三項演算子や条件と組み合わせない
// 読みづらい例(避ける)
int stock = 10;
int take = 3;
int left = (stock -= take) >= 0 ? stock : 0; // 減らしつつ評価は混乱のもと
Java副作用(代入やデクリメント)を評価式に混ぜるのは避け、更新と判定を段階に分けると可読性と安全性が高まります。
実用例で身につける
例 1: カウントダウンと終了条件
public class Countdown {
public static void main(String[] args) {
int sec = 5;
while (sec > 0) {
System.out.println(sec + "...");
sec--;
}
System.out.println("Start!");
}
}
Java例 2: 逆順に出力(添字の安全設計)
public class ReversePrint {
public static void main(String[] args) {
String[] words = {"Java", "is", "fun"};
for (int i = words.length - 1; i >= 0; i--) {
System.out.println(words[i]);
}
}
}
Java例 3: 後置で現在値を使ってから減らす
public class UseThenDecrement {
public static void main(String[] args) {
int tickets = 3;
while (tickets > 0) {
System.out.println("issue #" + tickets--); // 現在の番号を表示してから減る
}
}
}
Java設計の指針(重要ポイントのまとめ)
前置は「先に減る」、後置は「使ってから減る」。式の中に混ぜると誤読が起きやすいので、単独の行やループ更新に限定すると安全です。x = x--; は減らないトラップなので、減らすだけなら x--; を単独で書きます。逆順走査では「開始位置」「終了条件」を明確にし、境界を外さない設計を徹底しましょう。short/byte/char は -- で動くが、計算が多いなら int に揃える。アンダーフローは静かに起きるため、範囲を見積もり long・境界チェックで守る。必要なら -= 1 で意図を明示し、更新と判定を分離する——この習慣が、デクリメントまわりのバグを大幅に減らします。
