はじめに
while文は“条件が先”のループ。設計次第で、
アプリの安心感と使い心地がグッと変わるよ。
この記事では、実務でよく出会う3シーン——
1. 入力バリデーション(正しく入力されるまで繰り返す)
2. データベースの逐次取得(ResultSet
を最後まで読む)
3. 状態が整うまでの待機(タイムアウト付き)
を、ポケモン世界の例えと一緒に、読みやすく整理するね。
🎒 入力バリデーション:レベルは 1〜100
センターの端末に「ポケモンのレベル」を入力。数字だけ&範囲は 1〜100!
import java.util.Scanner;
public class LevelInput {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Integer level = null; // 正常入力で 1..100 が入る
while (level == null) {
System.out.print("レベル(1-100, qで中止): ");
String s = sc.nextLine().trim();
if (s.equalsIgnoreCase("q")) {
System.out.println("中止しました。");
return; // また今度!
}
try {
int v = Integer.parseInt(s);
if (1 <= v && v <= 100) {
level = v;
} else {
System.out.println("→ 1〜100 の数字でお願い!");
}
} catch (NumberFormatException e) {
System.out.println("→ 数字で入力してね。");
}
}
System.out.println("設定レベル: " + level);
}
}
コツ
- 入力は
nextLine()
で一括受けしてから parse。 -
nextInt()
と混ぜると改行が残ってハマりやすい。 - 終了の道(q など) を用意すると、ユーザー体験が優しくなる。
📘 DBストリーム:図鑑を1件ずつ読む(ResultSet
)
図鑑データベースからポケモンを順に読み上げるよ。
件数が多くても、1行ずつ 無理なく処理!
import java.sql.*;
public class PokedexFetch {
public static void main(String[] args) throws Exception {
String url = "jdbc:postgresql://localhost:5432/pokedex";
String user = "postgres";
String pass = "password";
String sql = "SELECT name, type, hp FROM pokemon ORDER BY id";
try (Connection con = DriverManager.getConnection(url, user, pass);
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) { // ← ココが while の見せ場!
String name = rs.getString("name");
String type = rs.getString("type");
int hp = rs.getInt("hp");
System.out.printf("%s / %s / HP=%d%n", name, type, hp);
}
}
}
}
ポイント
-
while (rs.next())
は“次の行が読める間”だけ回る、条件先行型の王道パターン。 -
try-with-resources で
Connection/PreparedStatement/ResultSet
を自動クローズ。 - 件数が多いときは ページング(
LIMIT/OFFSET
)や WHERE 条件で分割するのも◎。
⏳ 状態待ち:準備が整うまで、でも待ちすぎない
レイドのマッチングが「準備OK」になるまで待ちたい。でも永遠には待てないよね?
public class ReadyWaiter {
public static void main(String[] args) {
long deadline = System.currentTimeMillis() + 5_000; // 最大5秒だけ待つ
int tries = 0;
while (!isReady() && System.currentTimeMillis() < deadline) {
sleep(100); // CPUを休ませる(スピンしない)
tries++;
}
if (!isReady()) {
System.out.println("⚠ 準備が間に合わなかった… また挑戦しよう");
} else {
System.out.println("いざ、出発! 試行回数=" + tries);
}
}
static boolean isReady() {
// ここでは外部状態を見て準備OKか判定する想定
return Math.random() < 0.2; // デモ用:たまに準備OKになる
}
static void sleep(long ms) {
try { Thread.sleep(ms); } catch (InterruptedException ignored) {}
}
}
ポイント
-
deadline
を先に決めると、待ち時間の上限がはっきりして安心。 - ループ内で必ず 状態が変わる可能性 を作る
(外部チェック・カウンタ更新・スリープなど)。 - ポーリングが嫌なら、ブロッキングAPI/イベント通知に寄せよう
(キューのtake()
など)。
🔍 ログと監視の型:回数・状態を見える化
「ほんとに回ってる?」「どの条件で止まった?」を後から追えると安心!
int guard = 10_000; // 非常口:無限ループになっても止まる
while (processing() && guard-- > 0) {
if (guard % 1000 == 0) {
System.out.println("進捗: 残りガード=" + guard);
}
}
if (guard <= 0) {
System.out.println("⚠ ガードで停止。条件を見直してね");
}
ポイント
- 本番では“ガード”は不要なことも多いけど、テスト中は強い味方。
- 観測できるログ(回数・残り時間・現在状態)をこまめに出すとデバッグが超ラク。
🪄 次回予告
最終回は while文あるあるエラー集。無限ループ、境界条件、浮動小数の比較、break/continue
の取り違い……“やっちゃいがち”をまとめて駆除していくよ!
ピッピカチュウ!!
あとがき
ここまで読んでくれてありがとう。実務の while、手に馴染んできたかな?
「この場面も知りたい!」があれば、ぜひコメントで教えてね。次回もよろしく!
💬 コメント・フィードバック歓迎!
「ここ分かりやすかった!」「ここもっと詳しく!」
「次は○○を扱って!」など、気軽にどうぞ。