1. はじめに
想像してみてください。あなたはコーヒーショップ向けのプログラムを書いています。ユーザーが飲み物を選び、それに応じて処理する必要があります。もちろん大量の if-else if-else を使うこともできますが、見た目はあまりよくありません:
if (choice == 1)
{
System.out.println("エスプレッソを選びました。");
}
else if (choice == 2)
{
System.out.println("カプチーノを選びました。");
}
else if (choice == 3)
{
System.out.println("ラテを選びました。");
}
else
{
System.out.println("そのような飲み物はありません。");
}
確かに、かさばって見えます。選択肢が 10 や 20 になったらどうでしょう?そこで役に立つのが switch 文です。変数の値に基づいて多数の選択肢からの分岐を、エレガントかつコンパクトに記述できます。
従来の switch の構文
switch の構文は次のとおりです:
switch (expression)
{
case value1:
// expression == value1 の場合の処理
break;
case value2:
// expression == value2 の場合の処理
break;
...
default:
// いずれの case にも一致しない場合の処理
break;
}
switch 文の構文
主要な要素:
- switch (expression) — その結果を各 case と比較する式。
- case value: — 式と比較される候補の値。
- break; — switch ブロックの実行を終了します(ない場合は次の case にフォールスルー)。
- default: — どの case にも一致しない場合に実行されます。
2. switch の使用例
例 1: 定番 — 飲み物の選択
コーヒーショップのメニューを実装してみましょう:
import java.util.Scanner;
public class CoffeeShop
{
public static void main(String[] args)
{
Scanner console = new Scanner(System.in);
System.out.println("飲み物を選んでください:");
System.out.println("1 - エスプレッソ");
System.out.println("2 - カプチーノ");
System.out.println("3 - ラテ");
int choice = console.nextInt();
switch (choice)
{
case 1:
System.out.println("エスプレッソを選びました。");
break;
case 2:
System.out.println("カプチーノを選びました。");
break;
case 3:
System.out.println("ラテを選びました。");
break;
default:
System.out.println("そのような飲み物はありません。");
break;
}
}
}
ここでの処理:
- ユーザーが飲み物の番号を入力します。
- 変数 choice の値が各 case と比較されます。
- 一致したら該当ブロックが実行され、続いて break が switch の実行を終了します。
- どれにも一致しなければ default が実行されます。
例 2: 文字列での切り替え
switch で使える型は多くありませんが、文字列は使えます。コマンドメニューに便利です:
import java.util.Scanner;
public class CommandMenu
{
public static void main(String[] args)
{
Scanner console = new Scanner(System.in);
System.out.println("コマンドを入力してください (start, stop, pause):");
String command = console.nextLine();
switch (command)
{
case "start":
System.out.println("プログラムを起動します!");
break;
case "stop":
System.out.println("プログラムを停止します。");
break;
case "pause":
System.out.println("一時停止。");
break;
default:
System.out.println("不明なコマンドです。");
break;
}
}
}
注意: switch における文字列の比較は大文字小文字を区別します! "Start" と "start" は別の文字列です。
3. 従来の switch がサポートする型は?
従来の switch で使用できる型は限られています:
- プリミティブの整数型: byte, short, char, int
- 列挙型: enum(これについては次の講義で説明します)
- 文字列: String — 大文字小文字を区別して比較されます
使用できないもの: boolean、float、double、配列、任意のクラスのオブジェクト(enum と String を除く)。
char の例
char grade = 'B';
switch (grade)
{
case 'A':
System.out.println("素晴らしい!");
break;
case 'B':
System.out.println("良い。");
break;
case 'C':
System.out.println("可。");
break;
default:
System.out.println("もう一度試してください。");
break;
}
4. break は必須: 書き忘れるとどうなる?
初心者に最も多いミスは break; の書き忘れです。次を見てみましょう:
int day = 2;
switch (day)
{
case 1:
System.out.println("月曜日");
break;
case 2:
System.out.println("火曜日");
case 3:
System.out.println("水曜日");
break;
default:
System.out.println("不明な曜日");
break;
}
結果:
火曜日
水曜日
なぜでしょうか?case 2 の後に break がないため、実行が次の case へフォールスルーします(これを fall-through と呼びます)。ときには便利ですが、多くの場合はミスです。
5. グルーピングされた case: 複数の値が同じ動作をするとき
複数の値で同じ動作にしたい場合は、次のように続けて書けます:
int month = 1;
switch (month)
{
case 12:
case 1:
case 2:
System.out.println("冬");
break;
case 3:
case 4:
case 5:
System.out.println("春");
break;
case 6:
case 7:
case 8:
System.out.println("夏");
break;
case 9:
case 10:
case 11:
System.out.println("秋");
break;
default:
System.out.println("不明な月");
break;
}
ここでは: month が 12、1 または 2 の場合、プログラムは "冬" を出力します。
6. 比較: switch と if-else
| シナリオ | if-else | switch |
|---|---|---|
| 分岐が多い場合 | 長い連鎖になり、可読性が下がる | 簡潔で、すべての選択肢が一望できる |
| 範囲の比較 | 使用できる(if (x > 5 && x < 10)) | 不可。特定の値のみ |
| 対応する型 | 任意 | 限定される(上記参照) |
| break の落とし穴 | なし | あり。必ず break に注意 |
7. switch での典型的なミス
ミス №1: break の書き忘れ
最もよくあるバグの原因です。break を書き忘れると、意図しない次の case まで実行されます。
ミス №2: 非対応の型
double、float、boolean を使おうとすると、コンパイラに拒否されます。
ミス №3: 大文字小文字の異なる文字列
ユーザーが "Start" を入力し、こちらは "start" を想定していると switch は一致しません。事前に文字列を同一のケースに揃えるのがよいでしょう:
switch (command.toLowerCase())
{
case "start":
// ...
}
ミス №4: case に変数(定数のみ可)
case で使えるのは定数だけです。変数を使うとコンパイルエラーになります。
ミス №5: 重複した case
同じ値の case が二つあると、コンパイラは許してくれません。
GO TO FULL VERSION