7.

Java 制御構文完全ガイド (if/switch/for/while)

編集
この記事の要点
  • 分岐: if/else / switch (古い文 + Java 14+ 新しい式) / 三項演算子
  • 繰り返し: for / 拡張 for / while / do-while
  • 脱出: break / continue / return / ラベル付き break
  • モダン: switch 式 (Java 14+)、Pattern Matching (Java 17+/21)、enhanced switch、try-with-resources
  • do-while最低 1 回は実行while は条件 false なら 0 回

if / else / else if

int score = 75;

if (score >= 90) {
    System.out.println("A");
} else if (score >= 70) {
    System.out.println("B");       // ← ここに入る
} else if (score >= 50) {
    System.out.println("C");
} else {
    System.out.println("F");
}

// 単一行は { } 省略可能だがバグの温床なので推奨しない
if (x > 0) System.out.println("positive");

三項演算子

// 条件 ? 真の値 : 偽の値
int age = 20;
String label = (age >= 20) ? "大人" : "未成年";

// ネストは可能だが読みにくい
String grade = score >= 90 ? "A"
             : score >= 70 ? "B"
             : score >= 50 ? "C" : "F";

// ★ null チェック
String name = (user != null) ? user.getName() : "(unknown)";
// Java 8+ は Optional 推奨
String name2 = Optional.ofNullable(user).map(User::getName).orElse("(unknown)");

switch (古い文と新しい式)

古い switch 文 (Java 13 以前)

int day = 3;
String name;
switch (day) {
    case 1:
        name = "月";
        break;                    // ★ break 忘れると次に流れる (fall-through)
    case 2:
        name = "火";
        break;
    case 3:
    case 4:
        name = "水or木";          // フォールスルーで複数 case
        break;
    default:
        name = "?";
        break;
}

新しい switch 式 (Java 14+)

// 矢印構文 -> はフォールスルーしない (break 不要)
String name = switch (day) {
    case 1 -> "月";
    case 2 -> "火";
    case 3, 4 -> "水or木";          // ★ カンマで複数 case まとめ
    default -> "?";
};

// 複数行は yield
String label = switch (day) {
    case 1, 2, 3, 4, 5 -> "平日";
    case 6, 7 -> {
        log.info("休日です");
        yield "休日";              // ★ switch 式の戻り値
    }
    default -> throw new IllegalArgumentException();
};

Pattern Matching (Java 21+)

// 型と値による分岐
sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double s) implements Shape {}

double area = switch (shape) {
    case Circle c -> Math.PI * c.r() * c.r();
    case Square sq -> sq.s() * sq.s();
};

// ガード節 (when)
String size = switch (n) {
    case Integer i when i < 0 -> "negative";
    case Integer i when i == 0 -> "zero";
    case Integer i -> "positive";
};

for 文

// 初期化; 条件; 更新
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// 2 つ並列
for (int i = 0, j = 10; i < j; i++, j--) {
    System.out.println(i + "," + j);
}

// 無限ループ
for (;;) {
    if (done) break;
}

// 拡張 for (for-each)
for (String name : names) {
    System.out.println(name);
}

while と do-while の使い分け

構文条件チェック最低実行回数
whileループ前0 回
do-whileループ後1 回
// while: 条件が最初から false なら 1 度も実行されない
int i = 10;
while (i < 5) {
    System.out.println(i);    // ★ 表示されない
}

// do-while: 必ず 1 回は実行
int j = 10;
do {
    System.out.println(j);    // ★ 10 を 1 回表示
} while (j < 5);

// 典型例: ユーザー入力ループ
String input;
do {
    System.out.print("Enter (q to quit): ");
    input = scanner.nextLine();
    process(input);
} while (!input.equals("q"));

break / continue / ラベル付き

for (int i = 0; i < 10; i++) {
    if (i == 3) continue;     // この回をスキップ → 0,1,2,4,5,6,7,8,9
    if (i == 7) break;        // ループ脱出   → 0,1,2,4,5,6
    System.out.println(i);
}

// ラベル付き break で多重ループ一気に脱出
outer:
for (int[] row : matrix) {
    for (int n : row) {
        if (n == -1) break outer;     // ★ 外側ループも脱出
    }
}

// ラベル付き continue で外側ループの次イテレーション
outer:
for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
        if (skip[i][j]) continue outer;   // 外側ループの次へ
    }
}

try-with-resources (Java 7+)

AutoCloseable を実装したリソースを自動で閉じます。finallyclose() を呼ぶ昔の書き方より安全。

// 自動クローズ
try (
    FileReader fr = new FileReader("a.txt");
    BufferedReader br = new BufferedReader(fr)
) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
}   // ★ ここで br → fr の順に自動 close

// 例外も自動でログ
try (Connection conn = DriverManager.getConnection(url);
     PreparedStatement ps = conn.prepareStatement(sql);
     ResultSet rs = ps.executeQuery()) {
    while (rs.next()) { ... }
}

null チェックの定番

// クラシック
if (user != null && user.getName() != null) {
    System.out.println(user.getName().length());
}

// Java 8+ Optional
Optional.ofNullable(user)
    .map(User::getName)
    .ifPresent(n -> System.out.println(n.length()));

// Objects ユーティリティ
String name = Objects.requireNonNullElse(user.getName(), "(unknown)");

// Objects.requireNonNull (ガード節)
public void setUser(User u) {
    this.user = Objects.requireNonNull(u, "user must not be null");
}

例外による制御

try {
    int n = Integer.parseInt(input);
} catch (NumberFormatException e) {
    System.err.println("not a number: " + input);
} catch (Exception e) {
    System.err.println("other: " + e);
} finally {
    System.out.println("always");
}

// マルチキャッチ (Java 7+)
try {
    ...
} catch (IOException | SQLException e) {
    log.error(e);
}

FAQ

Q: switch と if/else どちらを使う?
A: 比較対象が同じ変数で 3 つ以上の値で分岐するなら switch。範囲比較 (x > 0) は if。Java 14+ の switch 式は記述量が少なく推奨。

Q: 古い break 付き switch はもう不要?
A: Java 14+ は新しい矢印構文 (->) を強く推奨。fall-through バグの温床を排除できます。

Q: while(true) と for(;;) はどちらが好まれる?
A: 機能的に同じ。可読性は while (true)、コンパイラ警告を避けたいなら for (;;) という流派もある。

編集
Post Share
子ページ
  1. 条件分岐 (if文)
  2. 繰り返し処理(while文)
  3. 繰り返し処理
  4. 繰り返しの中断 (break)
  5. 繰り返しのスキップ (continue)
同階層のページ
  1. 基本的なルール
  2. 変数
  3. 演算子
  4. 標準ライブラリ
  5. 外部ライブラリ
  6. 制御構文
  7. リスト(配列)
  8. タプル
  9. セット
  10. 辞書(dict)
  11. クラスとメソッド
  12. 継承の概念と必要性
  13. 継承の構文
  14. コンストラクタ
  15. cookieの値の設定と取得
  16. 例外処理
  17. 例外を文字列で出力する方法
  18. httpリクエスト(curl)をする方法
  19. Responseオブジェクトの中身の確認
  20. 変数が空かどうか判定する方法
  21. タイムゾーンの設定と現在日時の取得と文字列化
  22. シングルクォーテーションとダブルクォーテーションの違い

最近更新/作成されたページ