Javaでswitch-case文を使いたいが、条件の書き方や処理をもっと効率化したいという方もいるでしょう。しかし、switch-case文は用途や自由度がそれほど高くないため、ifやswitch式よりも厳格にルールを守って使う必要があります。
そこで本記事は、switch-case文のケースラベルのルールや基本的な書き方、応用した使い方などを解説します。
目次
閉じる
1.Javaのswitch-case文とは
Javaでは、条件分岐する方法の1つとして「switch-case文」が使われます。
このswitch-case文とは、「switch」で処理を開始して、「case」の書き分けで分岐条件を行う構文のことです。これを「制御構文」と呼び、条件分岐や繰り返し(ループ)を含むif文やfor文のように使われます。
ちなみに、「case 1」「case "Normal"」のように、caseの後ろにつける「1」や「"Normal"」などの分岐要素は、「ケースラベル」と呼びます。
switch-case文のケースラベルの使用規則
ケースラベルには基本、プリミティブ型で「定数値」のみが使えるルールです。定数値とは、変数ではない値のことです。
後で値の変更ができず、一度値を入力するとプログラム内で同じ値が使われます。例えば、整数の「1」や1文字の「'a'」(大文字や記号などUnicode文字)などです。
int
char
byte
short
ただし、後から変わり得る値の計算式の使用は使えません。また、「boolean」のtrue/false値や範囲過多の「long」の値、誤差を含む「float」の値は、定数値を取れないか、処理の高速化に影響があるため、こちらも使用できないことになっています。switchの形で使えるのは後述のswitch式だけです。
Javaのswitch-case文には文字列を使用可能
switch-case文には、JDK7からオブジェクトの文字列が使えます。つまり、4つの数値型を基本とし、さらに「String(文字列型)」がケースラベルに使用可能です。
文字列の定数が可能となったことで、同時に定数の集合をあらわす「enum(列挙型)」も利用できます。例えば、文字列に""で囲った定数に「"Error"」、曜日を列挙した「"Sunday"」などです。もちろん、ケースラベルには日本語も使用できます。
フォール・スルーの防止
switch-case文の記述では、「フォール・スルー」を回避して正しいケースのみを実行させる必要があります。フォール・スルーとは、switch-case文に特有の現象で、「break;」を置かないために、下の値のケースも同時に実行される動作のことです。
例えば、条件が「2」で「case 2:」が実行される場合でも、「break;」を入れていないと次の「case 3:」も連続して実行されてしまいます。
switch (num) { case 1: System.out.println("はい"); case 2: System.out.println("いいえ"); case 3: System.out.println("どちらでも"); } |
出力結果:
「いいえ」
「どちらでも」
「いいえ」だけ表示したいのに、「どちらでも」が実行されてしまうのです。上記の例は、2つだけですが、下にもっと多くの条件分岐があれば、すべて出力されます。
そして、コンパイル時には実行エラーによる失敗も起こらないため、このミスに気づきにくいのです。注意しないと意図しない条件分岐が発生し、バグの原因となります。
if文との違い
switch-case文は、特にif文記述の簡易版として使用されます。ifほど自由度は高くありませんが、特殊なケースではswitch-case文を使用してコードを簡潔化するのです。そのため、読みやすくなった分だけif文より可読性の向上が見込めます。
2.Javaのswitch-case文の基本となる使い方
以下に、Javaのswitch-case文の基本的な書き方を紹介します。
数値
まずは整数の数値を条件として分岐する使い方です。下記の例では、プリミティブ型を使って直接的に定数「2」を変数「number」に格納し、switchに値を渡しています。
public class IntNumber { public static void main(String[] args) { int number = 2;
case 1: System.out.println("数値は1と一致です。"); break; case 2: System.out.println("数値は2と一致です。"); break; case 3: System.out.println("数値は3と一致です。"); break; default: System.out.println("それ以外の数値です。"); } } } |
また、caseごとにフォール・スルーを防止する「break;」、例外の処理「default:」を書くのもポイントです。
文字列
次に、文字列のStringをswitch-case文で条件分岐した例です。次の例では、「Error」という文字のステータスを変数「status」に格納して、switchに渡しています。
public class StringNumber { public static void main(String[] args) { String status = "Error";
case "Normal": System.out.println("正常に動作しています。"); break; case "Error": System.out.println("エラーが発生しました"); break; default: System.out.println("状態不明です"); } } } |
整数の数値と大きく異なる点は、変数への定数代入とケースラベルの文字を「""」(ダブルクォーテーションマーク)で囲っていることです。
enum
列挙型のenumでは、最初に整数や文字列などを列挙し、挙げた名称や数字を使ってswitch-case文を利用します。
モノの名前を列挙するため「列挙子」、もしくは不変のため「enum定数」と呼ばれるものです。下記の例では、変数の「today」でenum定数(列挙子)を渡してswitchでケースに合致する列挙子の条件を確認しています。
public class EnumWeek {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
Day today = Day.WEDNESDAY;
case MONDAY: System.out.println("今日は月曜日です。"); break; case TUESDAY: System.out.println("今日は火曜日です。"); break; case WEDNESDAY: System.out.println("今日は水曜日です。"); break; case THURSDAY: System.out.println("今日は木曜日です。"); break; case FRIDAY: System.out.println("今日は金曜日です。"); break; case SATURDAY: System.out.println("今日は土曜日です。"); break; case SUNDAY: System.out.println("今日は日曜日です。"); break; } } } |
定数はすべて大文字の命名規則から曜日は英語の大文字です。enumの要素名は慣習的に大文字で定義され、switch文ではこれらの要素名をそのまま使用します。これはJavaの型チェックにより、Dayタイプのenumのみが使用可能で、要素名を文字列として扱っているわけではありません。
ちなみに、変数「today」に代入せず、switch()内に「Day.WEDNESDAY」をそのまま入れることもできます。これは、Day.WEDNESDAYがDay型のenum定数であり、直接スイッチ式として使用できるためです。
ただし、「Day」は型名のため、switch()内に「Day」を直接入れることはできません。つまり、「switch(Day)」はNGの書き方です。もう少し説明すると、「Day day = Day.WEDNESDAY;」のように変数にして代入すれば、例と同様にswitch(day)と書くことができます。
サンプルコードを解説するものの中には、この規則を破って起用する例(コンパイルエラーとなる書き方)を紹介していることがあります。そのため、間違って使わないように注意が必要です。
関連記事
Java SE入門|最新バージョン、ダウンロード方法、Oracle製品ライセンスを解説
3.Javaでswitch-case文を応用した複数条件の使い方
基本的な書き方を押さえたら、次は、それを応用した使い方の例です。
Javaのswitch式でbreakなしの「yield文」
Javaのswitch-case文では、「break」をcaseの最後に置いて、フォール・スルーを回避するのが基本と先に述べました。しかし、breakを必要としない書き方が登場し、フォール・スルーを管理する必要がありません。それが「yield文」を使用したswitch式です。
「Java 14(正式リリース)」、oracleでは「Java SE 12」以降に登場した条件文の書き方です。コードも簡潔で使い勝手にも優れます。
public class YieldWeek { public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
Day today = Day.WEDNESDAY;
case MONDAY -> "月曜日"; case TUESDAY -> "火曜日"; case WEDNESDAY -> "水曜日"; case THURSDAY -> "木曜日"; case FRIDAY -> "金曜日"; case SATURDAY -> "土曜日"; case SUNDAY -> "日曜日"; default -> "不明な曜日"; }; System.out.println(message); } } |
特にswitch式は、基本のswitch-case文と明確に異なる点があります。それは、switch式が「戻り値を返す」ことです。戻り値として条件分岐の結果をcaseの外で使いたい場面は、switch式のyield文を活用します。
Javaのswitch-case文を複数ラベルで同一処理
Javaのswitch-case文では、ケースラベルと処理が同じになるケースがあります。その場合、個別に書くとコードが増えるため、同じ処理は省略して複数ラベルで管理することが可能です。
以下のソースコード例では、「平日」というメッセージ出力の処理を月曜日から日曜日まで同一処理としてまとめています。これで何度も同じ処理を書く必要がありません。
public class MatomeWeek {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
Day today = Day.WEDNESDAY;
case MONDAY: case TUESDAY: case WEDNESDAY: case THURSDAY: case FRIDAY: message = "平日です。"; break; case SATURDAY: case SUNDAY: message = "週末です。"; break; default: message = "不明な曜日"; break; }
} } |
また、単純な処理の曜日表示などはswitch式を使いましょう。yield文でコード量を減らして可読性も高められます。以下は、switch-case文をswitch式のyield文にしたソースコード例です。
public class YieldMatomeWeek {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
Day today = Day.WEDNESDAY;
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "平日です。"; case SATURDAY, SUNDAY -> "週末です。"; default -> "不明な曜日"; };
} } |
switch-case文で使えない型を文字列型に変換
switch-case文を使用したい場合に、取得する情報が数値型や文字列型以外で、日付型のケースもあります。その際は、文字列型に変える「型変換」を実行することが有効です。
以下では、日本の現在の日付を取得して、Date型を文字列型に変えてから、ケースラベルに値を渡すようにしています。
import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.TextStyle; import java.util.Locale;
public static void main(String[] args) { ZonedDateTime today = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
String dayOfWeek = today.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.JAPAN); String message; switch (dayOfWeek) { case "月曜日": message = "今日は月曜日です。"; break; case "火曜日": message = "今日は火曜日です。"; break; case "水曜日": message = "今日は水曜日です。"; break; case "木曜日": message = "今日は木曜日です。"; break; case "金曜日": message = "今日は金曜日です。"; break; case "土曜日": message = "今日は土曜日です。"; break; case "日曜日": message = "今日は日曜日です。"; break; default: message = "不明な曜日"; break; }
} } |
switch-case文の場合、Date型の変数は使えないため、文字列型への変換が必須です。
この例では、getDayOfWeek().getDisplayName()メソッドを使用して曜日を文字列として取得しています。また上記コードは、Java 14以降であればswitch式を使ってさらに簡潔化することもできます。
ただし、日付に基づく条件分岐は、場合によってはif-else文で処理する方がより適切なケースもあります。必要性を見極めて使い分けましょう。
Javaのswitch-case文とif文の組み合わせ
switch-case文では、ケースブロックごとにif文の処理を加えることができます。そのため、必要なブロックにだけif文を組み合わせることができます。
例えば、以下のソースコード例では、曜日の条件分岐だけでなく、平日の場合には祝日判定を行えます。
import java.time.LocalDate; import java.time.Month; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.HashSet; import java.util.Set;
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
ZoneId japanZone = ZoneId.of("Asia/Tokyo"); ZonedDateTime japanTime = ZonedDateTime.now(japanZone); LocalDate todayDate = japanTime.toLocalDate();
holidays.add(LocalDate.of(2025, Month.MARCH, 20)); //春分の日(3月)
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY:
if (holidays.contains(todayDate)) { message = "今日は国民の祝日です。"; } else { message = "今日はただの平日です。"; }
case SATURDAY, SUNDAY: message = "今日は週末です。"; break; default: message = "不明な曜日"; break; }
System.out.println(message); } } |
現在の日付をもとに、平日(月曜日から金曜日)のブロックにのみif文を追加しています。今回は3月の例のみ、「contains()」メソッドで祝日に指定した日付が含まれていれば、trueを返します。
上記をさらに、年中の国民の祝日をすべて「holidays」に設定すれば、その年度の祝日判定も可能です。こうしてswitch-case文にはif文を内部処理に入れられます。
必要なら、さらにその中のブロックにif文やswitch-case文を入れて複雑な内部構造(深いネスト)にもできるのです。その場合は、ループ制御にラベル付きのbreakを使用することで対応します。
関連記事
【2025年版】Javaの最新バージョン|確認方法やインストール方法を解説
Javaのdate型で日付取得の方法は?新APIクラスを使いこなすポイントを解説!
4.Javaのswitch-case文でよくある質問
ここでは、Javaのswitch-case文でよくある質問に回答します。
Javaのswitch-case文とswitch式、if文はどれを使うべき?
Javaでは基本構文にif文があり、その発展形としてswitch-case文やswitch式を学びます。そのため、どんな場合でもif文を最初に使う人は意外と珍しくありません。
しかし、switch-case文とswitch式とif文では、それぞれ特徴が異なっており、状況に応じた使い分けが不可欠です。
特にif文、switch-case文、switch式の順で構造が簡略化されます。コードの可読性の向上にはswitch-case文かswitch式ですが、条件式をそのままケースラベルにしたい場合は条件式も書けるif文やswitch式がおすすめです。
Javaのswitch-case文で使えない型は「型変換」すれば問題ない?
switch-case文では、確かに型変換すれば条件分岐の際にケースラベルとして使うことができます。しかし、ベストプラクティスを無視してまでswitch-case文を使う必要はありません。
例えば、longは範囲が広く、intに変換してもすべてを正しく変換して表すことはできないでしょう。switch-case文を無理に使うよりも、ケースごとに使い分けてif文やswitch式、他の制御構文を検討することが、後々の保守管理の可読性やメンテナンス性を高めるためには必要です。
Javaのswitch-case文を使うとエラーが出やすいのはなぜ?
Javaでswitch-case文を正しく使うには、Java特有の型の厳格さ、ケースラベルの規則やクラス全体の一貫性なども守り、予想外の挙動をしないようにコードを組む必要があります。
例えば、switch-case文ならbreakの書き忘れや型・変数の不一致、NG事項の使用などです。NG事項は以下のとおりです。
NGケース1.日付や入力の変数、Date型やScannerクラスを直接書く
NGケース2.真偽値の変数「boolean」を直接使う
NGケース3.計算結果の変数をそのまま入れる(コンパイル時定数が必要)
NGケース4.式・値へのnull使用
NGケース5.別のケースラベルに同一値
NGケース6.ケースをまたいだ別ケースでの初期化(未初期化になる)
NGケース7.値を返すことを前提とした使用(switch文は値を返さないがswitch式は返す)
特に、switch式とswitch-case文は混同されやすく、名前も似ているため気づかないうちにコードを書いてNG事項に抵触していることがあります。switch-case文を利用する際は特に注意しましょう。
関連記事
Javaのboolean型とは?if文の使い方や初期値・0/1・戻り値・参照渡しなど条件分岐方法を解説!
Java 21(LTS版)完全ガイド|インストール方法、新機能の紹介、最新バージョン動向を解説
5.まとめ
今回は、Javaのswitch-case文についてケースラベルの規則や基本の条件分岐の書き方、型変換の応用的な使い方まで紹介しました。switch-case文は、最低限の宣言や定数、変数・型の利用などを押さえておけば、入れ子構造で条件を加えて制御することができます。
ただし、switch式のほうがよりシンプルですし、if文のほうが自由度が高いのです。使うべきケースかそうでないかは個々の状況で判断が必要です。以上を参考に、Javaの条件分岐の最適化や実践的利用の方法に活用しましょう。
本記事が皆様にとって少しでもお役に立てますと幸いです。
「フリーランスボード」は、数多くのフリーランスエージェントが掲載するITフリーランスエンジニア・ITフリーランス向けの案件・求人を一括検索できるサイトです。
開発環境、職種、単価、稼働形態、稼働日数など様々な条件から、あなたに最適なフリーランス案件・求人を簡単に見つけることができます。
単価アップを目指す方や、自分の得意なスキルを活かせる案件に参画したい方は、ぜひ「フリーランスボード」をご利用ください。