Javaの制御構造徹底解説

2025-08-01

はじめに

Javaプログラミングにおいて、制御構造はプログラムの流れをコントロールするための基本的かつ重要な要素です。すでにデータ型、変数、配列を学習したあなたにとって、次に習得すべきはこれらの制御構造でしょう。この記事では、条件分岐(if/switch)とループ(for/while)について、基礎から応用まで詳細に解説します。

制御構造を理解することで得られるメリット:

  • プログラムに判断能力を持たせられる
  • 繰り返し処理を効率的に記述できる
  • コードの可読性と保守性が向上する
  • より複雑なアルゴリズムを実装できるようになる

条件分岐:if文

基本的なif文の構文

if文は、条件に基づいて処理を分岐させる最も基本的な制御構造です。

if (条件式) {
    // 条件がtrueの場合に実行されるコード
}

具体例:

int age = 20;

if (age >= 20) {
    System.out.println("成人です");
}

if-else文

条件が成立しない場合(falseの場合)の処理を追加できます。

if (条件式) {
    // 条件がtrueの場合
} else {
    // 条件がfalseの場合
}

具体例:

int score = 65;

if (score >= 60) {
    System.out.println("合格です");
} else {
    System.out.println("不合格です");
}

if-else if-else文

複数の条件をチェックする場合に使用します。

if (条件式1) {
    // 条件式1がtrueの場合
} else if (条件式2) {
    // 条件式2がtrueの場合
} else {
    // すべての条件がfalseの場合
}

具体例:成績評価

int score = 78;

if (score >= 90) {
    System.out.println("評価:A");
} else if (score >= 80) {
    System.out.println("評価:B");
} else if (score >= 70) {
    System.out.println("評価:C");
} else if (score >= 60) {
    System.out.println("評価:D");
} else {
    System.out.println("評価:F");
}

ネストしたif文

if文の中にさらにif文を入れることができます。

int age = 25;
boolean hasLicense = true;

if (age >= 20) {
    if (hasLicense) {
        System.out.println("車をレンタルできます");
    } else {
        System.out.println("免許証が必要です");
    }
} else {
    System.out.println("20歳以上でないとレンタルできません");
}

条件式の書き方のコツ

  1. 複合条件:論理演算子を使用して複数の条件を組み合わせる
   if (age >= 20 && hasLicense) {
       System.out.println("レンタル可能");
   }
  1. 早期リターン:条件が満たされない場合に早めに処理を終了する
   if (age < 20) {
       System.out.println("20歳未満は利用できません");
       return;
   }
  1. 可読性向上:複雑な条件は変数に分離する
   boolean isEligible = age >= 20 && hasLicense && !isDrunk;
   if (isEligible) {
       System.out.println("運転可能");
   }

条件分岐:switch文

switch文の基本構文

switch文は、一つの変数の値に応じて多岐に分岐する場合に便利です。

switch (式) {
    case 値1:
        // 式が値1に等しい場合の処理
        break;
    case 値2:
        // 式が値2に等しい場合の処理
        break;
    // 必要なだけcaseを追加
    default:
        // どのcaseにも該当しない場合の処理
}

具体例:曜日判定

int dayOfWeek = 3;
String dayName;

switch (dayOfWeek) {
    case 1:
        dayName = "月曜日";
        break;
    case 2:
        dayName = "火曜日";
        break;
    case 3:
        dayName = "水曜日";
        break;
    case 4:
        dayName = "木曜日";
        break;
    case 5:
        dayName = "金曜日";
        break;
    case 6:
        dayName = "土曜日";
        break;
    case 7:
        dayName = "日曜日";
        break;
    default:
        dayName = "無効な日";
}
System.out.println(dayName);  // "水曜日"と表示

break文の重要性

switch文では、各caseブロックの最後にbreakを記述しないと、次のcaseブロックも実行されてしまいます(フォールスルー)。

int num = 2;
switch (num) {
    case 1:
        System.out.println("1");
    case 2:
        System.out.println("2");  // 実行される
    case 3:
        System.out.println("3");  // breakがないためこれも実行される
    default:
        System.out.println("default");  // これも実行される
}
// 出力結果:
// 2
// 3
// default

Java 12以降の拡張switch式

Java 12以降では、より簡潔なswitch式が導入されました。

String dayType = switch (dayOfWeek) {
    case 1, 2, 3, 4, 5 -> "平日";
    case 6, 7 -> "週末";
    default -> "無効";
};

switch文 vs if文

特徴switch文if文
適した場面単一変数の値による分岐複雑な条件式が必要な場合
可読性値による分岐が明確条件式が柔軟
パフォーマンスジャンプテーブル使用で高速な場合あり条件評価が必要
使用可能な型整数型、文字型、文字列型、enumすべてのboolean条件

ループ構造:for文

基本的なfor文

for文は、指定した回数だけ処理を繰り返す場合に使用します。

for (初期化式; 条件式; 更新式) {
    // 繰り返し実行する処理
}

具体例:1から10まで表示

for (int i = 1; i <= 10; i++) {
    System.out.println(i);
}

for文の動作フロー

  1. 初期化式が実行される(ループ開始時に1回のみ)
  2. 条件式が評価され、trueならループ内の処理を実行
  3. ループ内の処理が終了後、更新式が実行される
  4. 再度条件式を評価し、trueなら処理を繰り返す

さまざまなfor文の使用例

逆順のループ:

for (int i = 10; i >= 1; i--) {
    System.out.println(i);
}

ステップを2ずつ増加:

for (int i = 0; i <= 10; i += 2) {
    System.out.println(i);  // 0, 2, 4, 6, 8, 10
}

複数の変数を管理:

for (int i = 0, j = 10; i < j; i++, j--) {
    System.out.println("i: " + i + ", j: " + j);
}

拡張for文(for-each文)

配列やコレクションの要素を順番に処理する簡潔な構文です。

for (要素の型 変数名 : 配列またはコレクション) {
    // 各要素に対する処理
}

具体例:配列の処理

int[] numbers = {1, 2, 3, 4, 5};

for (int num : numbers) {
    System.out.println(num);
}

具体例:文字列配列の処理

String[] fruits = {"Apple", "Banana", "Orange"};

for (String fruit : fruits) {
    System.out.println(fruit);
}

ループ構造:while文

while文の基本構文

while文は、条件がtrueである限り処理を繰り返します。

while (条件式) {
    // 繰り返し実行する処理
}

具体例:1から10まで表示

int i = 1;
while (i <= 10) {
    System.out.println(i);
    i++;
}

do-while文

do-while文は、最低1回は処理を実行し、その後条件をチェックします。

do {
    // 繰り返し実行する処理
} while (条件式);

具体例:ユーザー入力の検証

import java.util.Scanner;

Scanner scanner = new Scanner(System.in);
int input;

do {
    System.out.print("1から10の間の数を入力してください: ");
    input = scanner.nextInt();
} while (input < 1 || input > 10);

System.out.println("正しい入力: " + input);

while文 vs for文

特徴while文for文
適した場面繰り返し回数が不明な場合繰り返し回数が明確な場合
初期化ループ外で行う初期化式内で行える
更新処理ループ内で行う更新式で行える
可読性条件のみに集中初期化・条件・更新が一箇所

ループ制御文

break文

break文は、ループを途中で終了させます。

for (int i = 1; i <= 10; i++) {
    if (i == 5) {
        break;  // iが5になるとループを抜ける
    }
    System.out.println(i);
}
// 出力: 1 2 3 4

continue文

continue文は、現在の繰り返しをスキップし、次の繰り返しに進みます。

for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
        continue;  // 偶数の場合はスキップ
    }
    System.out.println(i);
}
// 出力: 1 3 5 7 9

ラベル付きbreak/continue

ネストしたループで外側のループを制御する場合に使用します。

outerLoop:  // ラベル
for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
        if (i * j > 4) {
            break outerLoop;  // 外側のループを抜ける
        }
        System.out.println(i + " * " + j + " = " + (i * j));
    }
}

実践的な使用例

素数判定プログラム

int number = 29;
boolean isPrime = true;

if (number <= 1) {
    isPrime = false;
} else {
    for (int i = 2; i <= Math.sqrt(number); i++) {
        if (number % i == 0) {
            isPrime = false;
            break;
        }
    }
}

System.out.println(number + (isPrime ? " は素数です" : " は素数ではありません"));

フィボナッチ数列の生成

int n = 10;  // 生成する項の数
int a = 0, b = 1;

System.out.println("フィボナッチ数列:");
for (int i = 1; i <= n; i++) {
    System.out.print(a + " ");
    int sum = a + b;
    a = b;
    b = sum;
}

九九表の表示

for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= 9; j++) {
        System.out.printf("%2d ", i * j);
    }
    System.out.println();
}

よくある間違いとベストプラクティス

よくある間違い

  1. 無限ループ
   while (true) {  // 条件が常にtrue
       System.out.println("無限ループ");
       // 終了条件がない
   }
  1. セミコロンの誤配置
   if (condition); {  // セミコロンがあるとif文が終了してしまう
       System.out.println("常に実行される");
   }
  1. 浮動小数点数の比較
   for (double d = 0.1; d != 1.0; d += 0.1) {  // 誤差が発生する可能性
       System.out.println(d);
   }

ベストプラクティス

  1. ループ条件はシンプルに:複雑な条件はループ内でif文を使用
  2. 無限ループ防止:必ず終了条件を確認
  3. 適切なループ選択:回数が決まっているならfor文、条件ベースならwhile文
  4. 早期break:不要な処理を避けるため、条件が満たされたらすぐにループを抜ける
  5. ネストは浅く:深いネストは可読性を低下させる

練習問題

理解を深めるための練習問題を用意しました。実際にコードを書いて試してみましょう。

問題1: 成績判定プログラム

点数を入力すると、以下の基準で成績を判定するプログラムを作成してください。

  • 90点以上: A
  • 80~89点: B
  • 70~79点: C
  • 60~69点: D
  • 60点未満: F

問題2: 数当てゲーム

1から100までの乱数を生成し、ユーザーがその数を当てるゲームを作成してください。ユーザーの入力に対して「大きい」「小さい」とヒントを出し、正解したら試行回数を表示してください。

問題3: 素数表示プログラム

1から100までの素数のみを表示するプログラムを作成してください。

問題4: パターン表示

以下のパターンを表示するプログラムを作成してください。

*
**
***
****
*****

問題5: 配列操作

整数配列を受け取り、その中の最大値と最小値を見つけるプログラムを作成してください。

次のステップ

制御構造をマスターしたら、以下のトピックに進みましょう:

  1. メソッド - コードの再利用と構造化
  2. 配列とコレクション - データの効率的な管理
  3. 例外処理 - エラーへの対処方法
  4. オブジェクト指向プログラミング - クラスとオブジェクト

さらに学ぶためのリソース:

まとめ

この記事では、Javaの制御構造について詳細に解説しました。重要なポイントをまとめます:

  1. if文は条件に基づいて処理を分岐させる
  2. switch文は単一変数の値に応じて多岐分岐する
  3. for文は指定回数の繰り返し処理に適している
  4. while文は条件ベースの繰り返し処理に適している
  5. break/continueでループの制御が可能
  6. 適切な制御構造の選択がコードの可読性を向上させる

制御構造はプログラミングの基礎中の基礎です。実際にコードを書いて練習することで、確実に身につけていきましょう。最初は簡単なプログラムから始め、徐々に複雑な処理に挑戦していくのが上達のコツです。Happy coding!