【ITニュース解説】Can you have a try without a catch in Java?
2025年09月09日に「Dev.to」が公開したITニュース「Can you have a try without a catch in Java?」について初心者にもわかりやすく解説しています。
ITニュース概要
Javaでは、tryブロックはcatchがなくてもfinallyブロックと組み合わせれば使用できる。finallyは例外発生の有無に関わらず実行され、リソース解放などに使われる。catchがない場合、例外は呼び出し元に伝播し、未処理ならプログラムは停止する。
ITニュース解説
Javaプログラミングを学ぶ上で、エラー処理は避けて通れない重要なテーマである。プログラムの実行中に予期せぬ問題、すなわち「例外」が発生した場合に、プログラムが突然停止してしまうのを防ぎ、適切に対処するための仕組みが例外処理だ。その中心的な構文としてtry-catchブロックが知られている。一般的に、例外が発生する可能性のあるコードをtryブロックで囲み、発生した例外をcatchブロックで捕捉して処理するというのが基本的な使い方だ。このことから、多くの初心者はtryブロックには必ずcatchブロックがペアで必要だと考えがちである。しかし、Javaの仕様では、必ずしもそうとは限らない。結論から言えば、Javaではtryブロックをcatchブロックなしで使用することが可能だ。ただし、そのためにはfinallyブロックを組み合わせる必要がある。tryブロックは、単独で存在することはできず、必ずcatchブロックかfinallyブロック、あるいはその両方を伴わなければならない。これを守らない場合、プログラムはコンパイルエラーとなり、実行することすらできない。
では、catchブロックの代わりに使われるfinallyブロックとは、一体どのような役割を担うのだろうか。finallyブロックの最も重要な役割は、「後処理」を確実に実行することにある。後処理とは、例えばプログラム中で開いたファイルを閉じる、データベースへの接続を切断する、ネットワーク通信を終了するといった、使用したリソースを解放するためのクリーンアップ作業を指す。こうしたリソースは、使い終わったら必ず解放しなければ、システムに負荷をかけ続け、メモリリークやパフォーマンス低下といった深刻な問題を引き起こす可能性がある。finallyブロックに記述されたコードは、tryブロック内の処理が正常に完了したか、あるいは途中で例外が発生して中断されたかにかかわらず、必ず実行されることが保証されている。この特性により、finallyブロックはリソースの安全な解放処理を記述するのに最適な場所となるのだ。
catchブロックがないtry-finally構文の動作を具体的に見てみよう。まず、tryブロック内のコードが例外を発生させることなく、すべて正常に実行された場合、処理の流れは単純だ。tryブロックの実行が完了した後、続いてfinallyブロック内のコードが実行される。問題は、tryブロックの実行中に例外が発生した場合だ。このとき、tryブロック内の処理はその場で中断され、プログラムの制御は直ちにfinallyブロックに移る。そして、finallyブロックに記述されたクリーンアップ処理が実行される。ここが重要な点だが、finallyブロックの処理が完了した後、発生した例外はどこにも捕捉されていないため、消えてなくなるわけではない。その例外は、現在のメソッドを呼び出した元のメソッド、すなわち「呼び出し元」へと投げられる。これを例外の「伝播」と呼ぶ。もし呼び出し元のメソッドでも例外が捕捉されなければ、さらにその呼び出し元へと伝播していき、最終的にプログラムの最上位まで到達しても誰も処理しない場合、プログラムは異常終了し、コンソールにエラーの詳細(スタックトレース)が出力されることになる。
この動作を理解すると、try-catch構文とtry-finally構文の目的の違いが明確になる。try-catchの主目的は、例外をその場で捕捉し、処理することだ。例外が発生してもプログラムを停止させず、エラーログを記録したり、ユーザーに通知したり、代替の処理を行ったりして、プログラムの実行を継続させるために使用される。一方、try-finallyの主目的は、例外の処理そのものではなく、後処理を確実に実行することにある。例外自体への対処は呼び出し元に委ねるという設計思想に基づいている。つまり、このメソッドではリソースの解放という自身の責任は果たすが、発生したエラーへの具体的な対応は、より上位のコンテキストを理解している呼び出し元に任せる、という役割分担を可能にする。もちろん、try-catch-finallyという形で3つすべてを組み合わせることもできる。この場合、tryで例外を検知し、catchで例外を処理し、その後でfinallyの後処理を実行するという、最も包括的なエラーハンドリングが実現される。
結論として、Javaではtryブロックはcatchブロックがなくてもfinallyブロックがあれば有効な構文として成立する。finallyブロックは、例外の発生有無にかかわらずクリーンアップ処理を保証する極めて重要な機能を提供する。catchブロックなしで例外が発生した場合、その例外は呼び出し元に伝播し、最終的に処理されなければプログラムは停止する。このtry-finallyの仕組みを正しく理解することは、リソース管理を適切に行い、堅牢で信頼性の高いシステムを構築する上で不可欠な知識であると言える。