補足記事

switchって何?

条件分岐といえばif文を思い浮かべると思いますが、switch文を使って条件分岐を作ることも出来ます。値ごとに処理を切り替える書き方と、breakの役割を見てみましょう。

if文については既に理解していることを前提に説明しますので、先にif文って何?を読んでおくと分かりやすいと思います。

switchとは

まずswitch文の簡単な例を見てみましょう。以下のコード例は、それぞれSwitchExample.javaのmainメソッド内に書く部分を抜き出しています。

SwitchExample.java

int num = 2;
switch (num) {
    case 1:
        System.out.println("もっと頑張りましょう");
        break;
    case 2:
        System.out.println("普通です");
        break;
    case 3:
        System.out.println("大変よく出来ました");
        break;
}
実行結果
普通です

numの値によって、まさにスイッチで切り替えるように処理内容を分岐させています。numが2なので、「普通です」が出力されます。

もしこれをif文で書こうと思ったら、こうなります。

SwitchExample.java

int num = 2;
if (num == 1) {
    System.out.println("もっと頑張りましょう");
} else if (num == 2) {
    System.out.println("普通です");
} else if (num == 3) {
    System.out.println("大変よく出来ました");
}

else if(num == ○)が何個も続くと、なんとなく読みにくく感じませんか? switchだと、caseを使うことで、( )の中の値ごとに処理を分岐させることが出来ます。

最後に「その他」を付けることも出来ます。defaultを使います。

SwitchExample.java

int num = 2;
switch (num) {
    case 1:
        System.out.println("もっと頑張りましょう");
        break;
    case 2:
        System.out.println("普通です");
        break;
    case 3:
        System.out.println("大変よく出来ました");
        break;
    default:
        System.out.println("評価不能です");
}

この例でもnumは2なので「普通です」が出力されます。numを4など、どのcaseにも当てはまらない値に変えると、「評価不能です」が出力されます。defaultを省略したこの形式のswitch文では、どのcaseにも当てはまらなければ、何もせずswitch文の次へ進みます。

if文だと最後にelseを付ければ「その他」になりますよね。

SwitchExample.java

int num = 2;
if (num == 1) {
    System.out.println("もっと頑張りましょう");
} else if (num == 2) {
    System.out.println("普通です");
} else if (num == 3) {
    System.out.println("大変よく出来ました");
} else {
    System.out.println("評価不能です");
}

このように、switch文でもif文と同じような分岐を作ることが出来ます。ある変数の値によって処理を分岐させたい場合は、switch文で書いた方がちょっとスッキリします。

ここで使っているcase 値:という形式では、そのcaseの処理だけで終えたいところにbreak;を書きます。breakについては次節で詳しく説明します。

if文とswitch文の違い

同じような処理が出来るif文とswitch文ですが、もちろん違いはあります。その違いに着目しながら、もう少し理解を深めましょう。

if文の( )には、trueかfalseで判定する条件式を書きます。一方、ここまでのswitch文では、( )に比較したい値を書いています。変数だけでなく、計算式なども書けます。その値に合うcaseが実行の開始位置になります。

ただし、そのcaseの処理だけを実行させようと思ったら、breakを書くのを忘れてはいけません。例えば、こんなswitch文を見て下さい。breakが無い場合です。

SwitchExample.java

int num = 2;
switch (num) {
    case 1:
        System.out.println("もっと頑張りましょう");
    case 2:
        System.out.println("普通です");
    case 3:
        System.out.println("大変よく出来ました");
    default:
        System.out.println("評価不能です");
}

これを実行すると、

実行結果
普通です
大変よく出来ました
評価不能です

と出力されます。numは2なのに、「普通です」だけでなく、その後の二つも出力されています。

caseはあくまで「そこから処理を始める」ための目印です。この形式では、処理を始めた後に次のcaseの条件を調べ直すわけではなく、そのまま下の処理へ進みます。これをフォールスルーと呼びます。

そこで、caseの最後にbreakを書くことで、その場でswitch文を抜けるようにするわけです。一方、if・else if・elseをつなげた一つの分岐では、選ばれたブロックだけが実行され、次のelse ifやelseの処理へ流れ込むことはありません。

最後に置いたdefaultの処理が終わると、そのままswitch文の末尾に到達するので、そこでbreakを書いても書かなくても結果は同じです。returnなどで処理を終える場合もあるので、breakが常に必須という意味ではありません。

この仕組みを逆手に取ることで、複数の値に同じ処理をさせることも出来ます。

SwitchExample.java

int num = 2;
switch (num) {
    case 1:
    case 2:
        System.out.println("numは1か2です");
        break;
    case 3:
        System.out.println("numは3です");
        break;
    default:
        System.out.println("numは1、2、3以外です");
}
実行結果
numは1か2です

こんな風にcase 1とcase 2を続けて書けば、numが1でも2でも同じ処理になります。仕切りをぶち抜いた感じです。ただし、共有する処理の後にはbreakを書きます。これがないと、numが1や2でも、続けて「numは3です」まで出力されてしまいます。

SwitchExample.java

int num = 2;
switch (num) {
    case 1 -> System.out.println("もっと頑張りましょう");
    case 2 -> System.out.println("普通です");
    case 3 -> System.out.println("大変よく出来ました");
    default -> System.out.println("評価不能です");
}

この例でも「普通です」だけが出力されます。複数の値をまとめるなら、case 1, 2 ->のように書けます。一つのswitchブロックの中で「:」形式と「->」形式を混ぜることは出来ません。

switchで使える変数の型

ここまでの例ではswitchの( )の中にint型の変数を入れていました。従来の、値をcaseの定数と比較するswitchで使う代表的な型は、次のとおりです。

分類型
基本データ型byte、short、char、int
対応するラッパークラスByte、Short、Character、Integer
文字列String(Java 7以降)
列挙型enumで定義した型(Java 5以降)

基本データ型が全部使えるというわけではありません。ラッパークラスは基本データ型の値をオブジェクトとして扱うためのクラス、enumは決まった候補を列挙して作る型です。まずはintやStringで使えることを覚えておきましょう。

各caseの定数は、switchの( )に書いた式の型に対応できる値でなければなりません。例えば、int型の値と文字列の「"2"」は比較できません。

SwitchExample.java

int num = 2;
switch (num) {
    case 1:
        break;
    case "2":  // intの値に文字列は対応しないのでコンパイルエラー
        break;
}

これはコンパイルエラーです。また、通常のcaseに書くのは、数値や文字列のリテラル、定数式、列挙定数などです。実行中に値が変わる普通の変数を、そのままcaseの値として書くことは出来ません。

もう一つ、Stringなどの参照型で気を付けたいのがnullです。

SwitchExample.java

String str = null;
switch (str) {
    case "Java":
        System.out.println("Javaです");
        break;
    default:
        System.out.println("その他です");
}

このコードはコンパイルできますが、実行するとNullPointerExceptionという例外が発生します。defaultを書いていても、この例ではnullを受け止めてくれません。

以上、switch文にはif文よりもスッキリ書ける場面があります。まずはcase・defaultで処理を分け、「:」形式ではbreakで抜ける、という使い方を押さえて下さい。

全講座の目次へ戻る

質問・コメント

0件

この記事についての質問や、学習して気づいたことをお寄せください。

コメントを書く

コメントの受付は準備中です。入力しても送信・保存されません。

コメントと一緒に公開される名前です。
3,000文字以内。パスワードなどの個人情報は書き込まないでください。

コメントは管理者の承認後に公開されます。

この記事のコメント

まだコメントはありません。

受付開始後、承認されたコメントがここに表示されます。