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

Java入門

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

switch(基本から新機能まで)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

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

コードレビューをしていると、if-else if文が延々と続いているコードによく出会います。

「ここはswitch文を使えば、もっとすっきり読みやすくなるのに」と感じる場面が多いです。

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

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

この記事でわかること

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

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

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

Javaのswitch文とは何かを示す基本概念の図解

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

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

if文との違い

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

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

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

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

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

java
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文の基本的な形は以下のようになります。

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

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

Javaのswitch文の使い方を示す図解

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

int型やString型での使用例

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

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

java
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では使えませんでしたので注意が必要です。

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を連続して書く方法がありました。

java
    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の書き忘れ)

java
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;
}

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

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

numは1なので、case 1:の処理が実行されます。

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

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

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

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

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

Javaのswitch式の新構文を示す図解

Java 14(JEP 361で正式導入。最初のLTSで使えるのはJava 17)から、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式で書き換えてみます。

java
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 とカンマ区切りでまとめられます。
  • -> "冬" のように、返す値を書くだけで良く、breakもseason = "冬";のような代入文も不要です。
  • switch式全体が1つの文であるため、最後に;が必要です。

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

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

yieldの使い方と注意点

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

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

java
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式では、フォールスルーが発生します。

java
// 悪い例(コロン構文でのフォールスルー)
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以降が使える環境であれば、基本的には->を使うことをお勧めします。breakもyieldも不要で、バグが入り込む余地が少ないためです。

あわせて読む

パターンマッチング(Java 21)でさらに進化

Java 21(LTS)では、JEP 440(レコードパターン)とJEP 441(switchのパターンマッチング)が正式導入されました。

これにより、switch式はさらに進化しています。caseラベルに直接「型パターン」を書けるようになったのです。

java
sealed interface Shape permits Circle, Square {}
record Circle(double radius) implements Shape {}
record Square(double side) implements Shape {}

static double area(Shape shape) {
    return switch (shape) {
        // 型パターン + レコードパターンでフィールドを直接取り出せる
        case Circle(double radius) -> Math.PI * radius * radius;
        case Square(double side) -> side * side;
        // sealedで全実装クラスが分かっているため、defaultが不要
    };
}

sealed interface(継承・実装できるクラスを限定する仕組み)と組み合わせると、コンパイラが「すべての実装クラスをcaseで網羅しているか」をチェックしてくれます。

網羅できていなければコンパイルエラーになるため、default漏れのようなバグを未然に防げます。

さらにwhen句を使うと、パターンに追加の条件(ガード)を付けられます。

java
static String describe(Circle circle) {
    return switch (circle) {
        // whenで「半径が10より大きい」という追加条件を指定
        case Circle c when c.radius() > 10 -> "大きな円";
        case Circle c -> "小さな円";
    };
}

従来のswitch式が「値」による分岐だったのに対し、パターンマッチングは「型」と「構造」による分岐まで表現できる、より強力な機能です。

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

Javaのswitch文を使うときの注意点と落とし穴を示す図解

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

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

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

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

long型が使えないのは、言語仕様(JLS §14.11)でswitchに渡せる型がchar・byte・short・intと参照型に限られているためです。

float型やdouble型(浮動小数点数)も同じ理由でswitch文には使えません。そもそも浮動小数点数は、0.1 + 0.2が0.3に「正確に」一致しないなど、値がぴったり一致するかで分岐する用途には向きません。

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

なお、上の「使える型」はJava 20以前の従来のcaseラベル(定数)での話です。Java 21以降はパターンマッチング(後述)により、型パターンを使えば任意の参照型(sealed interfaceやrecordなど)もswitchに渡せます(long・boolean・float・doubleは、JDK 21でもselector type long is not allowedのようなコンパイルエラーです)。

breakの書き忘れによるバグ

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

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

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

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

defaultが実行されないケース

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

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

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

「switch文は使うべきでない」という意見について

オブジェクト指向設計の観点から、「型による分岐はswitch文ではなくポリモーフィズム(オーバーライド)で置き換えるべきだ」という意見を見かけることがあります。

例えば、動物クラスの種類ごとに鳴き声を変えたい場合を考えます。

switch文で分岐させるより、各サブクラスでcry()メソッドをオーバーライドするほうが拡張性に優れます。

新しい動物クラスを追加するたびに、switch文を修正する手間がなくなるためです。

ただし、これは「型ごとに振る舞いを変える」場面での話です。

メニュー選択やenumの状態分岐のように「1つの値を複数の定数と比較する」だけの単純な処理では、switch文やswitch式のほうがシンプルで読みやすくなります。

実際に、数千行のif-elseが連なる「モンスターメソッド」を保守した経験があります。

何か一つ条件を追加するたびに、既存の全条件分岐との組み合わせを確認する必要があり、修正が苦痛でした。

この処理をポリモーフィズムで設計し直したところ、追加・修正にかかるコストが約1/5にまで下がりました。

switch文であっても、caseの数が増え続け「型による分岐の乱立」に近づいてきたら、設計を見直すサインです。

「switch文を使うな」という意見は、「常にswitch文を避けるべき」という意味ではありません。

「型ごとの振る舞いの違いをswitch文で表現しようとしていないか、一度立ち止まって考えるべき」という設計上の注意喚起だと理解するのが適切です。

switch文の実践活用例

Javaのswitch文の実践的な活用例を示す図解

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

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

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

あわせて読む
java
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として使いやすいのです。

あわせて読む
java
// 信号のenum
public enum Signal {
    RED,
    YELLOW,
    BLUE
}
java
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が足りなければコンパイルエラーになるため、バグを未然に防げます。

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

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

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

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

java
// 良くない例: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() {
    // ... 参照処理
}

よくある質問

Q1. switch文とif文はどちらを使うべきですか?

A1. 1つの変数が3つ以上の特定の定数と比較される単純な分岐にはswitch文、範囲指定や複数変数の組み合わせなど複雑な条件にはif文が向いています。

Q2. switch文でbreakを忘れるとどうなりますか?

A2. 「フォールスルー」が発生し、そのcaseの処理が終わっても次のcaseの処理までそのまま実行されてしまいます。意図しない場合はバグの原因になります。

Q3. switch式とswitch文の違いは何ですか?

A3. switch式(Java 14以降)は値を返せる点が最大の違いです。アロー構文(->)を使うためbreakが不要でフォールスルーせず、コンパイラによる網羅性チェックも受けられます。

Q4. switch文で使えないデータ型は何ですか?

A4. long、boolean、float、doubleは使えません。int、byte、short、char(およびそのラッパー型)、String(Java 7以降)、enum(Java 5以降)が使える型です。

Q5. Java 21のパターンマッチングとは何ですか?

A5. JEP 440(レコードパターン)とJEP 441(switchのパターンマッチング)により、caseラベルに型パターンを直接書けるようになった機能です。sealed interfaceと組み合わせると網羅性チェックも受けられます。

Q6. switch文は使うべきではないという意見は本当ですか?

A6. 「型ごとに振る舞いを変える」場面ではポリモーフィズムが適していますが、「1つの値を複数の定数と比較する」単純な分岐にはswitch文やswitch式が適しています。用途による使い分けが重要です。

まとめ|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コードを目指しましょう。

REVISIONS / 改訂履歴
REV.DATE内容
32026-10-04記載内容の事実確認と修正
22026-09-042026年9月時点の情報で全体を見直し
12025-11-03初版
  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

-Java入門