演算子と制御構造の要点
内容の確認日: 2026-10-04
この分野では、分岐と繰り返しの文法に加えて、Java SE 14 で正式に入った switch 式が大きなテーマです。従来の switch 文との違い (値を返す・フォールスルーしない・すべての値を網羅する) を正確に押さえましょう。
出題項目は「分岐文 (if、if/else、switch) の使用」「繰り返し文 (do/while、while、for 文および拡張 for 文) の使用」「break、continue を使用した制御」「switch 式の使用」の 4 つです。break・continue がどの文に効くかも、細かく問われます。
switch 文の 2 つの書き方
switch 文には、従来の case 値: の形と、Java SE 14 からの case 値 -> の形があります。-> の形では、case 1, 2, 3 -> のようにカンマで複数の値をまとめられ、break を書かなくてもフォールスルーしません。
public class Main { public static void main(String[] args) { int day = 6; switch (day) { case 1, 2, 3, 4, 5 -> System.out.println("平日"); case 6, 7 -> System.out.println("週末"); default -> System.out.println("不明"); } }}java Main 週末
1 つの switch の中で、: の形と -> の形を混ぜて書くことはできません。: の形では、これまでどおり break がないと次の case に進みます。
switch 式
switch 式は、switch 全体が 1 つの値になる「式」です。int price = switch (...) { ... }; のように変数に代入したり、メソッドの引数に渡したりできます。式なので、最後の } の後ろにセミコロンが必要です。
-> の右側に書いた値が、そのまま switch 式の値になります。右側を { } のブロックにした場合は、yield 値; で値を返します。-> の右側には、例外を投げる throw も書けます。
public class Main { public static void main(String[] args) { String size = "M"; int price = switch (size) { case "S" -> 300; case "M", "L" -> { int base = 400; yield size.equals("L") ? base + 100 : base; } default -> throw new IllegalArgumentException(size); }; System.out.println(price); }}java Main 400
switch 式は必ず値を返さなければならないので、条件式のとり得るすべての値を case で網羅する必要があります。int や String は値が無数にあるので、default がないとコンパイルエラーです。
public class Main { public static void main(String[] args) { int n = 3; String s = switch (n) { case 1 -> "one"; case 2 -> "two"; }; System.out.println(s); }}javac Main.java
コンパイルエラー (4 行目): switch 式が int のすべての値を網羅していない (default がない)
列挙型 (enum) を条件式にした場合は、すべての列挙定数を case に書けば網羅したことになり、default は不要です。
enum Level { LOW, MID, HIGH }public class Main { public static void main(String[] args) { Level level = Level.MID; int score = switch (level) { case LOW -> 1; case MID -> 2; case HIGH -> 3; }; System.out.println(score); }}java Main 2
switch 式でも case 値: の形を使えます。その場合は switch 文と同じくフォールスルーし、値は yield で返します。
繰り返し文の実行順序
while (n-- > 0) のような条件では、比較は元の値で行い、その後で 1 減らします。ループの中で使われる値と、ループを抜けた後の値を区別して追いましょう。
public class Main { public static void main(String[] args) { int n = 3; while (n-- > 0) { System.out.print(n + " "); } System.out.println("/ " + n); }}java Main 2 1 0 / -1
do-while 文の中の continue は、ループの先頭ではなく、末尾の条件式の判定に進みます。条件が false なら、そこでループは終わります。
public class Main { public static void main(String[] args) { int i = 0; do { i++; if (i == 2) continue; System.out.print(i + " "); } while (i < 4); System.out.println(); }}java Main 1 3 4
while (true) や条件を省略した for (;;) は無限ループとみなされます。中に break がない場合、ループの後ろの文には到達できないので、コンパイルエラーになります。
public class Main { public static void main(String[] args) { while (true) { System.out.println("loop"); } System.out.println("end"); }}javac Main.java
コンパイルエラー (6 行目): 無限ループの後ろの文には到達できない
break と continue が効く範囲
ラベルのない break は、それを囲む一番内側の switch 文または繰り返し文を抜けます。if 文は対象ではないので、ループの外の if の中に break を書くとコンパイルエラーです。continue は繰り返し文だけが対象で、switch 文の中に書いた continue は、switch を囲むループの次の回に進みます。
public class Main { public static void main(String[] args) { for (int i = 0; i < 4; i++) { switch (i) { case 1: continue; case 2: break; default: System.out.print("d" + i + " "); } System.out.print(i + " "); } System.out.println(); }}java Main d0 0 2 d3 3
i == 1 のときは continue で for の次の回に進むので、switch の後ろの出力も飛ばされます。i == 2 のときの break は switch を抜けるだけで、switch の後ろの出力は実行されます。
ループにラベルを付けると、break ラベル; でそのループごと抜け、continue ラベル; でそのループの次の回に進めます。
public class Main { public static void main(String[] args) { outer: for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { if (j > i) continue outer; System.out.print(i * j + " "); } } System.out.println(); }}java Main 1 2 4 3 6 9
拡張 for 文とコレクションの変更
拡張 for 文でリストの要素を順に取り出している最中に、そのリスト自身の remove や add で要素数を変えると、次の要素を取り出すときに ConcurrentModificationException が発生します。
import java.util.ArrayList;import java.util.List;public class Main { public static void main(String[] args) { List<String> list = new ArrayList<>(List.of("a", "b", "c")); for (String s : list) { if (s.equals("a")) { list.remove(s); } } System.out.println(list); }}java Main
実行時に例外が発生: ConcurrentModificationException
条件に合う要素をまとめて削除したいときは、list.removeIf(s -> s.equals("a")); のように removeIf を使うと安全です。
試験でよくある引っかけ
switch式の網羅intやStringのswitch式でdefaultがないとコンパイルエラーです。enumはすべての定数を書けばdefault不要です。switch式の最後のセミコロンint x = switch (...) { ... };の最後の;は必要です (文ではなく式なので)。ブロックの値は
yield->の右側を{ }にした場合、値はreturnではなくyieldで返します。do-whileのcontinuedo-whileのcontinueは条件式の判定に進みます。条件がfalseならそこでループが終わります。switchの中のcontinueswitchの中のbreakはswitchを抜けるだけ、continueは外側のループの次の回に進みます。無限ループの後ろの文
breakのないwhile (true)の後ろに文を書くと、到達できないコードとしてコンパイルエラーです。
問題で確認する
この分野の問題を、解説つきで読めます (登録不要)。
出典・参考
- Oracle University 日本「Java SE 17 Programmer I (1Z0-825-JPN) 試験」
- JEP 361: Switch Expressions
- Java 言語仕様 (Java SE 17) 15.28「switch Expressions」
- Java 言語仕様 (Java SE 17) 14.15〜14.16「break・continue」
コード例は、試験の対象バージョンで実際にコンパイル・実行して結果を確認しています。