while 文の全体像
while 文は「条件が true のあいだ、繰り返し続ける」ための基本構文です。回数が決まっていない繰り返し(入力が尽きるまで、成功するまで、条件が変わるまで)に向いています。重要なのは「条件の設計」と「状態の更新場所」。ここが曖昧だと無限ループや取りこぼしが起きます。
基本形と動き
最小の書式
int i = 0;
while (i < 3) {
System.out.println(i);
i++; // 状態を更新(これがないと無限ループ)
}
Java「周回の頭で条件判定 → 本体実行 → 状態更新」という流れが基本です。while は「初回に条件が false なら一度も実行しない」点が、do-while との大きな違いです。
条件と更新のセット設計
int remain = 5;
while (remain > 0) { // 条件の軸:残数 > 0
System.out.println("remain=" + remain);
remain--; // 軸に対応する更新:1 減る
}
Java「条件(比較軸)と更新(変化軸)」をペアで考えると、境界バグが減ります。増やすなら「未満」、減らすなら「0より大きい」を基本形にすると安定します。
重要ポイントの深掘り:無限ループを防ぐ
更新漏れ・スキップの罠
continue を使うと、その周回の残りをスキップします。更新が本体の最後にある場合、continue で更新が飛ぶと無限ループの原因になります。
int i = 0;
while (i < 5) {
if (i == 2) {
i++; // スキップ前に更新を入れる(無限ループ回避)
continue;
}
System.out.println(i);
i++; // 通常更新
}
Java「更新は必ず通る」設計にするのが鉄則です。ガード条件で早めにスキップするなら、そこで更新も済ませるか、更新を先頭へ寄せる選択も有効です。
ブール旗より「明確な条件」
「終了条件が曖昧なフラグ」を後付けするより、ループの入口に終了条件を明示したほうが安全です。例えば「入力が空なら終了」「残タスクがゼロなら終了」など、実体に結びつけます。
do-while との違い(1回は必ず実行)
do-while の基本
int n = 0;
do {
System.out.println(n);
n++;
} while (n < 3);
Javado-while は「本体を先に1回実行してから条件判定」します。ユーザー入力のプロンプト表示や、最低1回は処理が必要な場面に向いています。初回実行が不要なら通常の while を使います。
入力・読み取りの定番パターン
スキャナで読み尽くす(hasNext)
import java.util.Scanner;
public class ReadAll {
public static void main(String[] args) {
Scanner sc = new Scanner("10 20 30");
int sum = 0;
while (sc.hasNextInt()) { // まだ整数があるか?
sum += sc.nextInt(); // 読み取り&累積
}
System.out.println(sum); // 60
}
}
Java「次がある間」という終了条件は、while の最も相性が良い形です。例外や不正値が来る可能性があるなら、ガード(hasNext...)を必ず前に置きます。
行読みで空行まで(番兵値/センチネル)
import java.util.Scanner;
public class UntilBlank {
public static void main(String[] args) {
Scanner sc = new Scanner("A\nB\n\nC\n");
String line;
while ((line = sc.nextLine()) != null && !line.isBlank()) {
System.out.println("read: " + line);
}
System.out.println("stop at blank");
}
}
Java「特定の値(空行)で終わる」センチネル方式は、while 条件で直接表現すると読みやすくなります。代入を条件に含めるときは副作用が明確で、短い一行に収まる場合に限りましょう。
continue・break・return の使い分け
反復スキップ/終了/メソッド終了
continue: 現在の周回の残りをスキップし、次周へ。break: ループ全体を終了し、外へ。return: メソッドを終了し、呼び出し元へ戻る。
int i = 0;
while (i < 5) {
if (i == 2) { i++; continue; } // 2 の回をスキップ
if (i == 4) break; // 4 の前で終了
System.out.println(i);
i++;
}
Java「どの範囲まで止めたいか」を明確にして、最小の制御文を選ぶとフローが読みやすくなります。
典型パターンと応用
条件付き集計(フィルタ+累積)
int[] arr = {3, -1, 8, -5, 2};
int i = 0, sum = 0;
while (i < arr.length) {
int v = arr[i];
if (v >= 0) sum += v; // 不正値は加算しない
i++;
}
System.out.println(sum); // 13
Java逆順処理(添字で制御)
String[] words = {"Java", "is", "fun"};
int i = words.length - 1;
while (i >= 0) {
System.out.println(words[i]);
i--;
}
Javaリトライと上限(カウンタ+条件)
int attempts = 0, maxAttempts = 3;
boolean success = false;
while (!success && attempts < maxAttempts) {
success = tryOnce(); // ここで実際の処理
attempts++;
}
System.out.println(success ? "OK" : "NG");
static boolean tryOnce() { return Math.random() < 0.4; }
Java「成功するまで、ただし上限まで」という「複合条件」は while の得意技です。必ず更新(attempts++)を通る設計にします。
よくある落とし穴と対策
オフバイワン(開始・終了のズレ)
開始位置と終了条件の整合が取れていないと、最後の要素を取りこぼしたり範囲外アクセスになります。書いたら「空、先頭、末尾」の3ケースで必ずチェックする習慣をつけましょう。
更新の一貫性
分岐によって更新が飛ぶと無限ループの原因に。更新を「先頭で必ず行う」「分岐ごとに必ず行う」など、ルールを決めて統一すると安全です。
複雑な式に副作用を混ぜない
while ((line = read()) != null && isOk(line)) は短くて有効ですが、ロジックが増えるなら「更新・判定・処理」を段階に分け、可読性を最優先にします。
while と for の使い分け
- 回数が決まっている、添字が必要、開始・終了・更新を一行に集約したいときは
for。 - 終了条件が外部要因(入力、成功判定、残タスク)に依存する、または1回ずつ明示更新したいなら
while。 - 「最低1回は実行」が必要なら
do-while。
使い分けを明確にすると、読み手が意図を瞬時に理解できます。
設計の指針(重要部分のまとめ)
- 入口に「終了条件」を明確に置く。比較軸と更新軸をペアで設計する。
- 更新は必ず通る設計にして、
continueで飛ぶ場合はその場で更新も行う。 - 入力・読み取りは「hasNext/センチネル」で条件化し、ガードを前に置く。
- 無限ループになりやすい箇所は小さく分解し、状態遷移を見える化する。
- 迷ったら「成功まで。ただし上限まで」の複合条件で、実務の安全策を組み込む。
