導入:なぜJavaにはgotoがないのか?
Javaエンジニアを目指すあなたが、他の言語で「goto文(無条件ジャンプ)」という言葉を耳にしたことがあるかもしれません。gotoは、プログラムの実行位置を強制的に別の場所へ移動させる命令です。しかし、Javaにはgotoが存在しません。なぜなら、gotoを多用するとコードの実行順序が予測困難になり、バグの温床(スパゲッティコード)になりやすいからです。Javaでは、gotoを使わずに、if-elseやswitchといった構造化された制御フローを使うことで、読みやすく堅牢なコードを書くことが推奨されています。本記事では、現代のJavaで主流の制御フローを解説します。
基礎知識:制御フローを理解する
Javaの制御フローとは、プログラムが上から下へ流れるだけでなく、条件によって分岐したり、繰り返し処理を行ったりする仕組みのことです。
・if-else:条件分岐の基本です。
・switch expressions:JDK 14以降で導入された強力な分岐構文。値を返すことができるのが特徴です。
・sealed classes:クラスの継承を制限する機能。switchと組み合わせることで、「網羅的な条件分岐」を安全に行えます。
実装:現代的な制御フローの書き方
昔のJavaのswitch文は、breakを書き忘れると次のケースまで実行されるというバグが頻発しました。しかし、最新のJavaでは「switch expressions」と「yield」キーワードを使うことで、より直感的で安全な記述が可能です。また、sealed classを使うと、特定のクラスしか継承できないため、switch文での条件漏れをコンパイル時に防ぐことができます。
サンプルプログラム:switch expressionsとsealed classesの活用
以下のコードをコピーして、最新のJava環境で動作確認してみてください。
public class FlowControlExample {
// sealedクラスで継承を制限(特定の型のみを許容)
public sealed interface Shape permits Circle, Square {}
public record Circle(double radius) implements Shape {}
public record Square(double side) implements Shape {}
public static void main(String[] args) {
Shape shape = new Circle(5.0);
// switch expressionsで値を直接取得
double area = switch (shape) {
case Circle c -> {
// 複数の処理が必要な場合はブロックとyieldを使用
double result = Math.PI c.radius() c.radius();
yield result;
}
case Square s -> s.side() s.side();
};
System.out.println(“図形の面積は: ” + area);
}
}
応用・注意点:現場で役立つポイント
1. gotoの代用としてのラベル付きbreak:Javaにも実は「ラベル」という機能があり、特定のループを多重に抜けることができます。しかし、これも多用するとgoto同様に可読性が下がります。本当に必要な場合のみ使いましょう。
2. 網羅性の確保:sealed classとswitchを組み合わせると、もし将来新しい図形(Triangleなど)を追加した際、switch文で処理を書き忘れるとコンパイルエラーになります。これにより、「条件の漏れ」というバグを未然に防ぐことができます。
3. 無理をしない設計:複雑な分岐が続く場合は、制御フローを重ねるのではなく、ポリモーフィズムを活用してオブジェクト指向的に解決できないか検討してみてください。それが、シニアエンジニアへの第一歩です。

コメント