導入:なぜ今、returnの書き方を見直すべきなのか
Javaの開発において、メソッドの最後で値を返す「return」は基本中の基本です。しかし、近年のJava(Java 17以降)では、従来のif-elseの多用から、より宣言的でバグを埋め込みにくい制御フローへと変化しています。複雑なif文による「ネストの深掘り」を解消し、堅牢なコードを書くために、現代的なreturnの扱い方を理解することは、シニアエンジニアを目指す上で避けて通れない道です。
基礎知識:制御フローのモダン化
かつてのJavaでは、条件分岐といえばif-else一択でしたが、現在は以下の要素を組み合わせるのが主流です。
switch expressions(switch式): 値を直接返すことができる新しいswitch文です。breakの書き忘れによるフォールスルー(意図しない動作)を防げます。
yield: switch式の中で、値を返すために使用するキーワードです。
sealed classes(シールクラス): 継承関係を制限し、switch式で「全てのパターンを網羅したこと」をコンパイラに保証させます。これにより、default句を書かずに済む安全な設計が可能になります。
実装/解決策:パターンマッチングで網羅性を高める
以前は「もし新しい型が増えたら、全てのif文を探して修正する」という作業が必要でしたが、sealed classesとswitch式を組み合わせることで、型を追加した瞬間にコンパイルエラーとして検知できるようになります。これにより、return漏れや処理の欠落を未然に防げます。
サンプルプログラム:モダンなreturnの活用例
以下のコードは、注文の状態に応じて送料を計算する例です。sealedクラスとswitch式を使い、非常に安全かつ簡潔に値をreturnしています。
// 注文状態を制限する(sealed class)
sealed interface OrderStatus {
record Pending() implements OrderStatus {}
record Shipped() implements OrderStatus {}
record Delivered() implements OrderStatus {}
}
public class ShippingCalculator {
public int calculateShipping(OrderStatus status) {
// switch式を使って直接returnする
return switch (status) {
case OrderStatus.Pending p -> {
// 複雑な計算が必要な場合はブロック内でyieldを使う
int baseFee = 500;
yield baseFee;
}
case OrderStatus.Shipped s -> 300;
case OrderStatus.Delivered d -> 0;
// コンパイラが全網羅をチェックするため、default句は不要
};
}
}
応用・注意点:現場で陥りやすい罠
シニアエンジニアとして注意してほしいのは、「何でもかんでもswitch式にすれば良いわけではない」という点です。
1. 副作用の回避: returnの代わりとなるswitch式は、本来「値を返すこと」に特化すべきです。式の中でDB更新などの副作用(Side Effect)を呼ぶのは避けましょう。
2. 網羅性の担保: sealed classを使わない場合、switch式では必ずdefault句が必要です。網羅性が保証されないコードは、将来的にバグの温床になります。
3. 可読性: if文の方が直感的な場合(単純なガード節など)は、無理にswitch式にする必要はありません。
「早期return(Early Return)」でネストを浅く保ちつつ、値の導出にはswitch式を活用する。この使い分けが、読みやすく保守性の高いJavaコードへの第一歩です。ぜひ、今日からの実装に取り入れてみてください。

コメント