Code Fix

中級

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構文が今も広く使われているため、両方を読めるようにしておく必要があります。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)