本ページはプロモーションが含まれています

Java入門

Javaのswitch文を徹底解説!基本から新機能まで

トム

・都内自社開発IT企業勤務/javaのバックエンドエンジニア
/java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎

Javaプログラミングを学んでいると、if文はすぐに習得できますが、switch文は少し戸惑うかもしれません。

コードレビューをしていると、if-else if文が延々と続いているコードによく出会います。「ここはswitch文を使えば、もっとすっきり読みやすくなるのに」と感じる場面が非常に多いです。

また、switch文を使っていても、breakを書き忘れて意図しないバグを生み出しているケースも見かけます。

この記事では、Javaのswitch文について知りたい方に向けて、以下の内容を解説します。

  • switch文の基本的な使い方とif文との違い
  • breakdefaultの正しい役割
  • Java 14から導入された新しい「switch式」の使い方

この記事を最後まで読めば、switch文のよくある落とし穴を避け、if文との使い分けを理解し、Java 14以降のモダンな書き方までマスターできます。

Javaのswitch文とは?基本の使い方を理解しよう

Javaのswitch文は、条件分岐を行うための構文の1つです。if文と似ていますが、特定の使い方に特化しています。

switch文は、1つの変数の値を調べ、その値がどのcaseに一致するかによって、実行する処理を振り分けます。

if文との違い

if文とswitch文は、どちらも条件分岐に使いますが、得意なことが異なります。

if文は、柔軟な条件設定が得意です。

例えば、「変数が10より大きいか?」「複数の変数の条件が同時に成り立つか?」といった複雑な比較(範囲指定や論理演算)に使われます。

if (score >= 80 && attendance >= 90) {
    System.out.println("合格です");
} else if (score >= 60) {
    System.out.println("追試です");
} else {
    System.out.println("不合格です");
}

一方、switch文は、1つの変数が特定の値と一致するかを比べる、単純な分岐が得意です。

int rank = 2;

switch (rank) {
    case 1:
        System.out.println("金メダル");
        break;
    case 2:
        System.out.println("銀メダル");
        break;
    case 3:
        System.out.println("銅メダル");
        break;
    default:
        System.out.println("入賞");
        break;
}

このように、rankという1つの変数が「1か?」「2か?」「3か?」と、特定の値と一致するかどうかで処理を分けています。

switch文が向いている場面

switch文は、if-else ifが長くなりすぎるときに使うと、コードが非常に読みやすくなります。

  • メニュー選択: ユーザーが「1: 登録, 2: 参照, 3: 終了」などを選ぶとき
  • ステータスによる分岐: 「"processing": 処理中, "completed": 完了, "error": エラー」などで処理を分けるとき
  • enum(列挙型)での分岐: 信号機の色(赤、青、黄)などで処理を分けるとき

if文でも書けますが、switch文のほうが「この変数の値によって分岐している」と、ひと目で分かりやすい利点があります。

構文の基本形(switch構文の書き方)

switch文の基本的な形は以下のようになります。

switch (式) {
    case 値1:
        // 値1に一致した場合の処理
        break;
    case 値2:
        // 値2に一致した場合の処理
        break;
    // ... 必要なだけcaseを続ける
    default:
        // どのcaseにも一致しなかった場合の処理
        break;
}
  • switch (式): ()の中には、比較したい変数や式を入れます。
  • case 値:: caseのあとには、比較対象となる「値」(定数)を書きます。:(コロン)で終わる点に注意してください。
  • break;: 各caseの処理の最後に書きます。これは非常に重要です(後述します)。
  • default:: どのcaseにも当てはまらなかったときに実行されます。if文のelseに相当します。

Javaのswitch文の使い方【基本構文と例文付き】

それでは、具体的なデータ型を使ったswitch文の例を見ていきましょう。

int型やString型での使用例

switch文でよく使われるのは、int(整数)とString(文字列)です。

int型の使用例(月の判定)

int month = 4;
String season;

switch (month) {
    case 12:
    case 1:
    case 2:
        season = "冬";
        break;
    case 3:
    case 4:
    case 5:
        season = "春";
        break;
    case 6:
    case 7:
    case 8:
        season = "夏";
        break;
    case 9:
    case 10:
    case 11:
        season = "秋";
        break;
    default:
        season = "不正な月です";
        break;
}

System.out.println(month + "月は" + season + "です。");
// 出力: 4月は春です。

String型の使用例(信号機)

String型は、Java 7からswitch文で使えるようになりました。それ以前のJavaでは使えませんでしたので注意が必要です。

String signal = "blue";
String action;

switch (signal) {
    case "red":
        action = "止まれ";
        break;
    case "yellow":
        action = "注意";
        break;
    case "blue":
        action = "進め";
        break;
    default:
        action = "不明な信号";
        break;
}

System.out.println("信号は" + signal + "、行動は" + action);
// 出力: 信号はblue、行動は進め

複数のcaseをまとめる方法(フォールスルー)

先ほどのint型の例で、case 12: case 1: case 2: のようにcaseを連続して書く方法がありました。

    case 12:
    case 1:
    case 2:
        season = "冬";
        break;

これは、breakを意図的に省略することで、複数のcaseで同じ処理を実行させるテクニックです。

case 12:に一致した場合、breakがないため、そのままcase 1:の場所に処理が進みます。case 1:にもbreakがないため、case 2:に進みます。

case 2:の処理(season = "冬";)が実行され、break;でswitch文を抜けます。

このように、breakがない場合に次のcaseの処理に進んでしまうことを「フォールスルー」と呼びます。

複数のcaseをまとめたいときには便利なテクニックですが、意図しないフォールスルーはバグの原因になります。

defaultの役割とは?

defaultブロックは、switch()内の式が、どのcaseの値とも一致しなかった場合に実行されます。

defaultは省略することも可能ですが、バグを防ぐために書くことを強く推奨します。

なぜなら、変数が想定外の値(例えば、月の例で13など)を持っていた場合に、defaultがないとswitch文全体が何も処理せずに終了してしまうからです。

defaultブロックでエラーメッセージを表示したり、ログを残したりすることで、想定外の事態に気づくことができます。

breakを省略した場合の挙動

switch文で最も注意すべき点が、breakの書き忘れです。

先ほど説明したフォールスルーは、breakの省略によって発生します。

もし、各caseの最後にbreakを書き忘れると、どうなるでしょうか。

悪い例(breakの書き忘れ)

int num = 1;

switch (num) {
    case 1:
        System.out.println("1が実行されました");
        // breakを忘れている!
    case 2:
        System.out.println("2が実行されました");
        break;
    case 3:
        System.out.println("3が実行されました");
        break;
}

このコードを実行すると、コンソールには以下のように出力されます。

1が実行されました
2が実行されました

numは1なので、case 1:の処理が実行されます。しかし、breakがないためswitch文を抜けず、そのまま次のcase 2:の処理も実行してしまいます。

case 2:にはbreakがあるため、そこでswitch文が終了します。

これがswitch文の最大の落とし穴です。意図しない処理が実行され、深刻なバグにつながる可能性があります。

caseの処理を書いたら、必ずbreak;を書くクセをつけましょう。

Java 14以降の新構文「switch式」とは?

Java 14(Java 17 LTSで本格導入)から、switchは大幅に進化しました。

従来のswitch文(statement)に加え、値を返すことができる「switch式(expression)」が登場したのです。

switch式は、従来のswitch文の欠点であった「breakの書き忘れ」や「冗長な記述」を解決する、非常に強力な機能です。

従来のswitch文との違い

switch式には、大きく分けて3つの利点があります。

ポイント

  1. 値を返せるswitch式は、それ自体が1つの「値」を持ちます。そのため、結果を直接変数に代入できます。
  2. breakが不要(フォールスルーしない)新しい構文では、フォールスルーがデフォルトで発生しません。breakの書き忘れによるバグがなくなります。
  3. 網羅性(もうらせい)のチェックswitch式では、考えられるすべてのcaseパターンを網羅しているか、コンパイラがチェックしてくれます(defaultの書き忘れなど)。

アロー構文(→)の書き方

switch式では、case 値: の代わりに case 値 -> というアロー構文を使います。

-> の右側に、実行したい処理や返したい値を書きます。-> を使うと、breakは不要です。

switch式の使用例(アロー構文)

先ほどの「月の判定」をswitch式で書き換えてみます。

int month = 4;

// switch式の結果を、直接season変数に代入する
String season = switch (month) {
    case 12, 1, 2 -> "冬"; // caseをカンマ(,)でまとめることができる
    case 3, 4, 5 -> "春";
    case 6, 7, 8 -> "夏";
    case 9, 10, 11 -> "秋";
    default -> "不正な月です";
}; // 式なので最後にセミコロン(;)が必要

System.out.println(month + "月は" + season + "です。");
// 出力: 4月は春です。

コードが劇的にすっきりしました。

注目すべき点は以下のとおりです。

  • switchの結果がString型として扱われ、season変数に代入されています。
  • case 12: case 1: case 2: のように縦に並べる必要がなく、case 12, 1, 2 とカンマ区切りでまとめられます。
  • -> "冬" のように、返す値を書くだけで良く、breakseason = "冬";のような代入文も不要です。
  • switch式全体が1つの文であるため、最後に;が必要です。

もし、-> の右側で複数の処理を行いたい場合は、{}(ブロック)で囲みます。

    case 1 -> {
        System.out.println("1が選ばれました");
        yield "処理A"; // 複数の処理がある場合はyieldで値を返す
    }

yieldの使い方と注意点

switch式で、->ではなく、従来の:構文を使いたい場合もあります。:のあとで複雑な処理を実行し、その結果として値を返したいときです。

その場合に、値を返すために使うのが yield キーワードです。

int num = 1;

String result = switch (num) {
    case 1:
        // numが1のときに、何か複雑な計算や処理を行う...
        System.out.println("case 1の処理を実行中...");
        yield "結果A"; // yieldを使って値を返す
    case 2:
        yield "結果B";
    default:
        yield "結果X";
};

case 1: のようにコロンを使った場合、breakの代わりにyieldで値を返します。yieldが実行されると、その時点でswitch式を抜けます。

注意点として、:構文を使ったswitch式では、フォールスルーが発生します

// 悪い例(コロン構文でのフォールスルー)
String result = switch (num) {
    case 1:
        System.out.println("case 1");
        // yieldを忘れるとフォールスルーする!
    case 2:
        System.out.println("case 2");
        yield "結果B"; // 1の場合もここが実行されてしまう
    default:
        yield "結果X";
};

Java 14以降が使える環境であれば、基本的には->を使うことをお勧めします。breakyieldも不要で、バグが入り込む余地が少ないためです。

あわせて読む

switch文を使うときの注意点と落とし穴

switch文には、いくつかの注意点が存在します。

条件式に使えないデータ型

switch()には、使えないデータ型があります。

  • 使える型: int, byte, short, char(および、これらのラッパー型 Integer, Byte, Short, Character)、String(Java 7以降)、enum(Java 5以降)
  • 使えない型: long, boolean, float, double

long型が使えないのは、Javaの歴史的な経緯によります。

float型やdouble型(浮動小数点数)は、0.1 + 0.2が0.3に「正確に」一致しないなど、値の比較が難しいため、switch文には使えません。

これらの使えない型で分岐したい場合は、if-else if文を使用する必要があります。

breakの書き忘れによるバグ

これは従来のswitch文における最大の注意点です。

breakを忘れるとフォールスルーが発生し、意図しないcaseブロックの処理まで実行されてしまいます。

コードレビューやテストで必ず確認すべきポイントです。

可能であれば、breakが不要なJava 14以降のswitch式への移行を検討しましょう。

defaultが実行されないケース

defaultブロックが実行されないのは、いずれかのcaseに処理が一致した場合です。

これは当然の動作ですが、テストの際に「caseに一致するパターン」しか試さず、「defaultに流れるべき想定外のパターン」のテストを忘れることがあります。

defaultが正しく動作するかどうかも、きちんとテストすることが重要です。

switch文の実践活用例

switch文が実際にどのように役立つか、いくつかの活用例を紹介します。

メニュー選択や入力処理に使う方法

コンソールアプリケーションなどで、ユーザーに入力を求め、その内容で処理を分岐させるのは典型的なswitch文の使い道です。

import java.util.Scanner;

Scanner scanner = new Scanner(System.in);
System.out.println("メニューを選んでください (1:登録 2:参照 9:終了)");
int input = scanner.nextInt();

switch (input) {
    case 1:
        System.out.println("登録処理を開始します");
        // ... 登録メソッド呼び出し
        break;
    case 2:
        System.out.println("参照処理を開始します");
        // ... 参照メソッド呼び出し
        break;
    case 9:
        System.out.println("アプリケーションを終了します");
        break;
    default:
        System.out.println("不正な入力です。1, 2, 9のいずれかを入力してください");
        break;
}

enum型と組み合わせた使い方

enum(列挙型)は、switch文と非常に相性が良いです。enumは取りうる値が限定されているため、switch文のcaseとして使いやすいのです。

// 信号のenum
public enum Signal {
    RED,
    YELLOW,
    BLUE
}
Signal currentSignal = Signal.RED;

switch (currentSignal) {
    case RED:
        System.out.println("止まれ");
        break;
    case YELLOW:
        System.out.println("注意");
        break;
    case BLUE:
        System.out.println("進め");
        break;
    // enumの場合、すべてのパターンを網羅していればdefaultは不要な場合もある
}

さらに、switch式とenumを組み合わせると、コンパイラが「enumのすべての値をcaseで網羅しているか」をチェックしてくれます。もしcaseが足りなければコンパイルエラーになるため、バグを未然に防げます。

// switch式とenumの組み合わせ(最強のパターン)
String action = switch (currentSignal) {
    case RED -> "止まれ";
    case YELLOW -> "注意";
    case BLUE -> "進め";
    // defaultが不要になる(すべてのenumを網羅しているため)
};

コードを見やすく整理するためのテクニック

switch文のcaseブロック内の処理が長くなりすぎると、かえってコードが読みにくくなります。

その場合は、caseの中にはメソッド呼び出しだけを書き、実際の処理は別のメソッドに切り出すのが良いテクニックです。

// 良くない例:caseの中が長い
switch (menu) {
    case 1:
        System.out.println("--- 登録処理 ---");
        System.out.println("名前を入力してください:");
        String name = scanner.next();
        // ... 処理が延々と続く
        break;
    case 2:
        // ... 参照処理が延々と続く
        break;
}

// 良い例:メソッドに切り出す
switch (menu) {
    case 1:
        doRegister(); // 処理をメソッド化
        break;
    case 2:
        doReference(); // 処理をメソッド化
        break;
}

private void doRegister() {
    System.out.println("--- 登録処理 ---");
    System.out.println("名前を入力してください:");
    // ... 登録処理
}

private void doReference() {
    // ... 参照処理
}

まとめ|Javaのswitch文を使いこなそう

Javaのswitch文は、条件分岐をすっきりと記述するための強力なツールです。

使うべき場面の判断基準

switch文を使うべきかif文を使うべきか迷ったときは、以下の基準で判断しましょう。

  • switch文が適している場面:
    • 1つの変数の値が、3つ以上の特定の定数(数値、文字列、enum)と比較されるとき。
    • if-else ifが長くなり、可読性が下がっているとき。
  • if文が適している場面:
    • 条件が2つ(if-else)の場合。
    • 条件が範囲指定(x > 10)や、複数の変数の組み合わせ(x > 10 && y < 5)であるとき。
    • long, doubleなど、switch文で使えない型を比較するとき。

switch式を使うメリット

Java 14以降の環境が使えるのであれば、従来のswitch文よりも、新しいswitch式(アロー構文 ->)を積極的に使うことを強く推奨します。

  • バグが減る: breakの書き忘れ(フォールスルー)がなくなります。
  • コードが簡潔になる: 値を直接変数に代入でき、caseの記述も短くなります。
  • 安全性が高い: enumなどと組み合わせると、網羅性チェックが働き、default漏れなどを防げます。

switch文の特性と注意点を正しく理解し、読みやすくバグのないJavaコードを目指しましょう。

  • この記事を書いた人
  • 最新記事

トム

・都内自社開発IT企業勤務/javaのバックエンドエンジニア
/java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎

-Java入門