導入
Java開発において、条件分岐は避けて通れません。しかし、if-else文の連発はコードの可読性を下げ、バグの温床になりがちです。特に「状態」や「種類」を扱う際、Enum(列挙型)とSwitch式を組み合わせることで、コンパイラが網羅性をチェックしてくれる「型安全」なコードが実現できます。本記事では、Java 17以降で標準となったSwitch式とSealed Class(封印クラス)を絡めた、現代的な制御フローの書き方を解説します。
基礎知識
Enum(列挙型)は、定数の集合を定義する特別なクラスです。これを用いることで、取りうる値が限定されるため、意図しない値の混入を防げます。
また、Java 12以降で導入されたSwitch式は、従来のswitch文とは異なり「値を返す」ことができます。これにより、変数の初期化をより宣言的に記述可能です。さらに、Sealed Class(封印クラス)と組み合わせると、継承先を限定できるため、Switch式での網羅性チェックがより強力に機能します。
実装/解決策
Switch式で重要なのは、すべてのパターンを網羅することです。Enumの全要素を列挙すれば、default句を省略可能です。これにより、後からEnumに値を追加した際、コンパイルエラーとして検知できるため、修正漏れを未然に防ぐことができます。また、複雑なロジックが必要な場合は、ブロック内でyieldキーワードを使って戻り値を指定します。
サンプルプログラム
以下のコードは、注文の状態に応じた処理をSwitch式で実装した例です。
public class OrderProcessor {
// 注文の状態を表すEnum
public enum OrderStatus {
PENDING, PROCESSING, SHIPPED, CANCELLED
}
public String processOrder(OrderStatus status) {
// Switch式を使用して、状態ごとに結果を返す
return switch (status) {
case PENDING -> “注文を待機しています。”;
case PROCESSING -> “発送準備中です。”;
case SHIPPED -> “発送済みです。”;
case CANCELLED -> {
// 複数行の処理が必要な場合はブロックを使用し、yieldで値を返す
System.out.println(“キャンセル処理を実行します…”);
yield “注文はキャンセルされました。”;
}
// Enumの場合、全てのケースを網羅していればdefaultは不要
};
}
public static void main(String[] args) {
OrderProcessor processor = new OrderProcessor();
System.out.println(processor.processOrder(OrderStatus.PENDING));
}
}
応用・注意点
現場での開発において、最も注意すべきは「網羅性」です。もしSwitch式でEnumの全てのケースをカバーしていない場合、コンパイルエラーが発生します。これは一見厳しいように見えますが、「Enumに新しい値を追加した際、修正が必要な箇所をコンパイラが教えてくれる」という強力なメリットになります。
また、Sealed Classと組み合わせる際は、`permits`句で継承関係を明確に定義してください。これにより、サブタイプが増えた場合も同様にコンパイラが網羅性を監視してくれます。if-elseの多用で悩んでいる方は、ぜひこの「網羅性チェック」を活かした設計に切り替えてみてください。コードの保守性が格段に向上します。

コメント