1. 導入:なぜ「戻り値」と制御フローが重要なのか
Javaでプログラミングをしていると、メソッドから値を返す「return」は避けて通れません。しかし、ただ値を返すだけでなく、「条件によって返す値を分岐させる」という処理は、コードの可読性に直結します。
if-else文だけで複雑な分岐を書くと、いわゆる「スパゲッティコード」になりがちです。今回は、Java 14以降で導入された「switch式」や「sealedクラス」を組み合わせ、簡潔で安全な戻り値の設計方法を解説します。
2. 基礎知識:戻り値と制御フローの役割
メソッドの戻り値(return value)とは、処理の結果を呼び出し元に渡す仕組みです。
これまで主流だったif-else文は、「処理の手順」を記述するのには向いていますが、値を決定する際には冗長になりやすいという欠点があります。
Javaの進化により、「処理結果を一つの式として評価する」という考え方が標準になりました。これにより、変数への代入漏れや、分岐の網羅性漏れ(コンパイルエラーで検知できる)を防ぐことができます。
3. 実装/解決策:switch式とsealedクラスの活用
現代のJava開発では、複雑な分岐をif-elseでネストさせるのではなく、switch式(switch expressions)を使って「値を代入する」スタイルを推奨します。
また、特定の型のみを許可するsealedクラスを組み合わせることで、「どのケースを考慮すべきか」をコンパイラが強制的にチェックしてくれるため、バグが劇的に減ります。
4. サンプルプログラム
以下のコードは、注文の状態に応じてメッセージを返す例です。コピーして実行してみてください。
// sealedクラスで状態を制限する(Java 17以降)
sealed interface OrderStatus permits Pending, Completed, Cancelled {}
record Pending() implements OrderStatus {}
record Completed() implements OrderStatus {}
record Cancelled() implements OrderStatus {}
public class OrderProcessor {
public static void main(String[] args) {
OrderStatus status = new Pending();
String message = getStatusMessage(status);
System.out.println(message);
}
public static String getStatusMessage(OrderStatus status) {
// switch式を使用。網羅性チェックが働くため、
// 処理漏れがあるとコンパイルエラーになるので非常に安全です。
return switch (status) {
case Pending p -> "現在処理中です。";
case Completed c -> "完了しました!";
case Cancelled ca -> "キャンセルされました。";
// defaultが不要なのは、sealedクラスで型が限定されているためです
};
}
}
5. 応用・注意点:現場で陥りやすい罠
実務で意識すべきポイントは以下の2点です。
・網羅性の確保
if-elseを使用する場合、最後に「else」を書き忘れて戻り値が未定義になるミスがよく発生します。switch式を使うと、すべてのケースを網羅しない限りコンパイルが通らないため、このミスを構造的に排除できます。
・yieldの活用
もしswitchの各ケース内で複雑な計算が必要な場合は、yieldキーワードを使って値を返却できます。
int result = switch (type) {
case 1 -> {
int temp = calculateExpensive(); // 複雑な計算
yield temp 2; // yieldで値を返す
}
default -> 0;
};
このように、戻り値を意識した設計を心がけるだけで、あなたの書くJavaコードの品質は一段階向上します。ぜひプロジェクトに取り入れてみてください。

コメント