switch で break を忘れるとどうなるか
次のcaseへ落ちるフォールスルーの挙動と、defaultの役割、String switchの書き方を扱います。
なぜエラーが出ないのか
出力: one / two
(エラーなし)- javacは何も報告しません。文法として正しいためです
出力: one / two- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 public class Main { 2 public static void main(String[] args) { 3 int n = 1; 4 switch (n) { 5 case 1: 6 System.out.println("one"); 7 ^ 8 case 2: 9 System.out.println("two"); 10 } 11 } 12 }
出力: one / two期待: one (コンパイルは通っています)
caseはbreakがないと次のcaseへ落ちます。これをフォールスルーと呼びます。
直し方: (空) を break; にします。
広告
広告スロット(未設定)
パターン2
1 public class Main { 2 public static void main(String[] args) { 3 int n = 9; 4 switch (n) { 5 case 1: System.out.println("one"); break; 6 case : System.out.println("other"); ^ 7 } 8 } 9 }
Main.java:6: error: illegal start of expression
どのcaseにも当たらないときの受け皿はdefaultです。caseには必ず値が要ります。
直し方: case を default にします。
パターン3
1 public class Main { 2 public static void main(String[] args) { 3 String cmd = "go"; 4 switch (cmd) { 5 case go : System.out.println("moving"); break; ^ 6 } 7 } 8 }
Main.java:5: error: cannot find symbol
symbol: variable go
switchでStringを扱うときも、caseの値は文字列リテラルとして書きます。
直し方: go を "go" にします。
パターン4
1 public class Main { 2 public static void main(String[] args) { 3 int n = 3; 4 switch (n) { 5 case 1..5 : ^ 6 System.out.println("small"); 7 break; 8 default: 9 System.out.println("other"); 10 } 11 } 12 }
Main.java:5: error: : or -> expected
switchのcaseに範囲指定の構文はありません。複数の値を1つの処理にまとめたいときは、caseを並べてフォールスルーさせます。
直し方: 1..5 を 1: case 2: case 3: case 4: case 5 にします。
パターン5
1 public class Main { 2 public static void main(String[] args) { 3 char grade = 'a'; 4 switch (grade) { 5 case "a": ^ 6 System.out.println("excellent"); 7 break; 8 } 9 } 10 }
Main.java:5: error: incompatible types: String cannot be converted to char
char型のswitchでは、caseの値もchar(シングルクォート)で書きます。ダブルクォートはStringになり型が合いません。
直し方: "a" を 'a' にします。
よくある誤解
フォールスルーはバグではなく仕様です。複数のcaseを同じ処理にまとめるときに、意図して使います。
実務での勘所
フォールスルーが事故の温床になりやすいことは言語設計側でも認識されており、Java 14で正式導入されたswitch式ではcase X -> 処理;という書き方ができ、matchしたcaseの処理だけを実行してbreakなしでも次のcaseに落ちません。新しく書くコードでは、この矢印構文を使うことでbreak忘れという問題そのものを避けられます。ただし既存のコードベースでは従来のcolon構文が今も広く使われているため、両方を読めるようにしておく必要があります。