05_制御文(if・switch)

対象:C言語経験者 / C言語との差分を中心に、試験頻出のswitch文フォールスルーを理解します


■ 1. if文(C言語とほぼ同じ)

if文の構文はC言語と全く同じです。条件式に boolean 型の値を使う点だけ意識しておきましょう。

C言語
if (a > 0) {
    printf("正\n");
} else if (a < 0) {
    printf("負\n");
} else {
    printf("ゼロ\n");
}
Java(全く同じ構文)
if (a > 0) {
    System.out.println("正");
} else if (a < 0) {
    System.out.println("負");
} else {
    System.out.println("ゼロ");
}

● C言語との唯一の違い:条件式に整数を使えない

// C言語ではOKだがJavaではコンパイルエラー
int flag = 1;
if (flag) { ... }      // エラー:int は boolean ではない

// Javaではこう書く
boolean flag = true;
if (flag) { ... }      // OK

// または比較式にする
int n = 1;
if (n != 0) { ... }    // OK
C言語では「0以外はtrue」という慣習がありましたが、Javaでは条件式は必ず boolean 型である必要があります。
試験では「if (n >= 0)」のような記述が問われます。

● この制約にはC言語のよくあるバグを防ぐ効果がある

C言語では == と書くつもりが = になっても動いてしまうため、発見しにくいバグになることがありました。

C言語:書き間違えても動いてしまう
int n = 3;
if (n = 5) {
    // == と書くつもりが = になった
    // n に 5 が代入され、0以外なので
    // 常に true になるバグ
    printf("ここが実行される\n");
}
Java:コンパイルエラーで気づける
int n = 3;
if (n = 5) {
    // コンパイルエラー!
    // int を boolean に使えないと
    // コンパイル時に教えてくれる
}
Javaが「条件式は必ず boolean」と決めたことで、=== の書き間違いをコンパイル時に検出できます。
これも「安全な言語」としてのJavaの設計思想のひとつです。

エラーを実際に確認しましょう

05_Grade フォルダに IfError.java を作って、あえてエラーになるコードを書いてみましょう。

public class IfError {
    public static void main(String[] args) {
        int n = 5;

        // ① int をそのまま条件式に使う → エラー
        if (n) {
            System.out.println("これはエラー");
        }

        // ② = を == と書き間違える → エラー
        if (n = 10) {
            System.out.println("これもエラー");
        }
    }
}

VSCode上での確認:

確認できたら、次のように修正して正しく動くことも確認しましょう:

public class IfError {
    public static void main(String[] args) {
        int n = 5;

        // 修正① 比較式にする
        if (n != 0) {
            System.out.println("n は 0 ではない");
        }

        // 修正② = を == に直す
        if (n == 10) {
            System.out.println("n は 10");
        } else {
            System.out.println("n は 10 ではない");
        }
    }
}
n は 0 ではない n は 10 ではない

■ 2. switch文(試験頻出:フォールスルーに注意)

● 基本構文

C言語
switch (x) {
    case 1:
        printf("one\n");
        break;
    case 2:
        printf("two\n");
        break;
    default:
        printf("other\n");
}
Java(ほぼ同じ)
switch (x) {
    case 1:
        System.out.println("one");
        break;
    case 2:
        System.out.println("two");
        break;
    default:
        System.out.println("other");
}

● C言語との差分

項目C言語Java
条件式に使える型整数型のみ整数型・charStringenum
条件式に boolean使えない使えない(同じ)
条件式に float/double使えない使えない(同じ)
フォールスルー(break 忘れ)起きる起きる(同じ)
Java では String を switch の条件式に使えます。これはC言語にはない機能です。
// JavaではStringをswitchに使える
String day = "Mon";
switch (day) {
    case "Mon":
        System.out.println("月曜日");
        break;
    case "Tue":
        System.out.println("火曜日");
        break;
    default:
        System.out.println("その他");
}

■ 3. フォールスルー(試験最頻出)

break を書かないと、次の case に処理が「落ちていく」現象をフォールスルー(fall through)と言います。これはC言語と同じ動作ですが、試験で繰り返し出題されます。

フォールスルーのイメージ

break がない case は、床に穴が空いているようなイメージです。処理が次の case に落ちていきます。

switch (a) { case 0: println("zero"); ← break なし! case 1: println("one"); break; case 2: println("two"); } a = 0 のとき case 0 に入る case 1 に落ちる break で抜ける 出力: zero one a = 1 のとき case 1 に入る break で抜ける 出力: one
case 0break がないため、a=0 のとき case 1 にも処理が流れます(フォールスルー)。

● フォールスルーを意図的に使うパターン

「複数の case に同じ処理をさせたい」ときに意図的に使うこともあります。

// 平日かどうかを判定する例
switch (day) {
    case 1:  // 月曜
    case 2:  // 火曜
    case 3:  // 水曜
    case 4:  // 木曜
    case 5:  // 金曜
        System.out.println("平日");
        break;
    case 6:  // 土曜
    case 7:  // 日曜
        System.out.println("休日");
        break;
}
このように処理を書かない case を並べてフォールスルーさせるのは意図的な使い方です。
一方、println のあとに break を書き忘れるのは意図しないフォールスルーで、バグになります。

■ 4. switchの条件式に使える型・使えない型

switch の条件式に使えるか
int(と byte, short, char使えます
String使えます(Java 7以降。C言語にはない)
enum(列挙型)使えます(後の単元で学びます)
long使えません(コンパイルエラー)
float / double使えません(コンパイルエラー)
boolean使えません(コンパイルエラー)
試験では「switch の条件式に long を使った → コンパイルエラー」という誤りパターンが出題されます。
int の範囲に収まる整数型のみ使えます(long は範囲が大きすぎるため不可)。

■ 実習1:if-else if を使った成績判定

実習1

05_Grade フォルダに Grade.java を作って実行しましょう。

public class Grade {
    public static void main(String[] args) {

        int score = 75;

        // if-else if-else による成績判定
        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("評価: D(不合格)");
        }

        // 条件演算子との比較(同じ判定を1行で)
        String grade = (score >= 60) ? "合格" : "不合格";
        System.out.println("合否: " + grade);
    }
}

実行結果(score = 75 の場合):

評価: B 合否: 合格

● 動いたら変えてみましょう

#変えてみること確認ポイント
1 score90, 70, 50, 30 に変えて4パターン確認する 境界値(ちょうど70や90)でどちらに分類されるか確認しましょう
2 条件を score > 90= なし)に変えてみる score = 90 のとき評価が A → B に変わることを確認しましょう。境界条件のミスはよくあるバグです
3 if (score) と書いてみる(条件に int を直接使う) コンパイルエラーになることを確認しましょう。C言語との違いです

■ 実習2:switchのフォールスルーを体験する

実習2

06_Switch フォルダに Switch.java を作って実行しましょう。

public class Switch {
    public static void main(String[] args) {

        // ① フォールスルーの確認(break なし)
        int a = 0;
        System.out.println("--- a=" + a + " ---");
        switch (a) {
            case 0:
                System.out.println("zero");
                // break がないので次に落ちる
            case 1:
                System.out.println("one");
                break;
            case 2:
                System.out.println("two");
                break;
        }

        // ② 試験第67回 問4(23) と同じパターン
        int val = 4;
        System.out.println("\n--- switch(val - val/2*2), val=" + val + " ---");
        switch (val - val / 2 * 2) {
            case 0:
                System.out.println("zero");
                // break なし → フォールスルー
            case 1:
                System.out.println("one");
        }

        // ③ Stringをswitchに使う(Javaだけの機能)
        String color = "red";
        System.out.println("\n--- color=" + color + " ---");
        switch (color) {
            case "red":
                System.out.println("赤");
                break;
            case "blue":
                System.out.println("青");
                break;
            default:
                System.out.println("その他");
        }
    }
}

実行結果:

--- a=0 --- zero one --- switch(val - val/2*2), val=4 --- zero one --- color=red --- 赤
② の val - val/2*2 がなぜ 0 になるのか確認しましょう

val = 4 のとき:

これは偶数のとき 0、奇数のとき 1 になる計算です。
val % 2(2で割った余り)と同じ意味になります。

第67回 問4(23) ではこの計算が case 0 にマッチし、break がないため case 1 にもフォールスルーして "zero" と "one" が両方出力されます。

● 動いたら変えてみましょう

#変えてみること確認ポイント
1 ① の case 0: の直後に break; を追加する フォールスルーが止まって "zero" だけ表示されることを確認しましょう
2 ② の val3(奇数)に変える 3 - 3/2*2 = 3 - 1*2 = 3 - 2 = 1 となり case 1 だけが実行されることを確認しましょう
3 ③ の color"RED"(大文字)に変える String の switch は大文字小文字を区別します。"その他" になることを確認しましょう

■ 試験(問4)との対応

頻出ポイント

よく問われること正しい答え
switch に break がないとき次の case に処理が流れる(フォールスルー)
switch の条件式に使えない型long, float, double, boolean
switch の条件式に String使えます(Java 7以降)
if の条件式に整数を直接使うコンパイルエラー(boolean 型が必要)
練習問題:次の出力を答えましょう(第67回 問4(23))
public class Q {
    public static void main(String[] args) {
        int a = 4;
        switch (a - a / 2 * 2) {
            case 0:
                System.out.println("zero");
            case 1:
                System.out.println("one");
        }
    }
}
zero one

a - a/2*2 = 4 - 2*2 = 0 なので case 0 に入ります。
② case 0 に break がないためフォールスルーして case 1 も実行されます。

練習問題2:次の出力を答えましょう(第67回 問4(27))
public class Q2 {
    public static void main(String[] args) {
        int n = -5;
        if (n >= 0) {
            System.out.print("Perl");
        } else if (n < -3) {
            System.out.print("PHP");
        } else {
            System.out.print("Python");
        }
    }
}
PHP

n = -5n >= 0 を満たさず、n < -3(-5 < -3)を満たすので "PHP" が出力されます。


■ まとめ

ポイント内容
if 文C言語と同じ。条件式は必ず boolean 型(整数不可)
switch のフォールスルーbreak がないと次の case に処理が流れる。試験最頻出
switch の条件式int, char, String, enum が使える。long, float, boolean は不可
String の switchJava 7以降で使える。C言語にはない機能
意図的フォールスルー処理なしの case を並べて複数の値に同じ処理をさせる