Java | 基礎文法:while 文

Java Java
スポンサーリンク

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);
Java

do-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/センチネル」で条件化し、ガードを前に置く。
  • 無限ループになりやすい箇所は小さく分解し、状態遷移を見える化する。
  • 迷ったら「成功まで。ただし上限まで」の複合条件で、実務の安全策を組み込む。

タイトルとURLをコピーしました