導入
こんにちは、もんすんです。
プログラミングを学んでいく中で、例外処理は避けて通れない重要なテーマです。
プログラムが実行中に予期しない問題が発生することはよくありますが、その際にどう対処するかがプログラムの安定性に大きく影響します。
今回は、初心者にも分かりやすく、例外処理の基本とその正しい使い方を解説していこうと思います。
例外を適切に処理する方法を理解することで、より堅牢で信頼性の高いプログラムを書くことができるようになります。
例外について
例外とは何か?
プログラムを実行しているときに発生する「予期しない問題」が例外です。
これらは、プログラムが正常に動作するために予測していなかったエラーや問題のことを指します。
プログラムが正しく実行されるためには、こうした例外を適切に処理することが必要です。
例えば、以下のような状況で例外が発生することがあります。
- 存在しないファイルを開こうとしたとき(例:
FileNotFoundException
) - 0で割り算をしたとき(例:
ArithmeticException
) - ネットワーク接続が切れたとき(例:
IOException
)
これらの問題が発生した際、そのままプログラムが進んでしまうと予期せぬ動作を引き起こし、大きなトラブルの原因になります。
例えば、計算結果が不正確になったり、システムがクラッシュしたりする可能性もあります。
そのため、例外を適切に検出し、処理を行うことが重要です。
例外を無視してはいけない理由
例外が発生した場合、その目的は「何か問題が起きたことを知らせる」ことです。
しかし、以下のように例外を無視してしまうコードを書くと、この目的が失われてしまいます。
try {
// 例外が発生する可能性のある処理
} catch (Exception e) {
// 空のcatchブロック:何もしない...
}
これは、「火災報知器が鳴っているのに、それを無視する」のと同じです。
本当に火事が起きているのかを確認せずに警報を無視してしまえば、後で大きな被害につながるかもしれません。
プログラムにおいても、例外を無視すると、その原因がわからずにバグや障害を引き起こす可能性が高くなります。
このような実装は品質の低いコードと見なされがちです。
例外が発生した理由を適切に理解し、その後の処理を考えることが、良いプログラムを作るための基本です。
正しい例外処理の基本
例外が発生したときに、どのように対応するべきかを理解しておくことは非常に重要です。
適切な例外処理を行うことで、プログラムの安定性を保ち、エラーが発生した場合でも、ユーザーに与える影響を最小限に抑えることができます。
正しい例外処理の基本としては、以下の3つが挙げられます。
-
例外を記録する
例外が発生した場合、その内容をログに残すことが重要です。
これにより、後から問題を追跡しやすくなり、原因特定や修正作業が迅速に行えます。 -
適切な処理を行う
例外が発生した場合、ただちにエラーを報告するだけでなく、適切な処理を行うことが大切です。
例えば、ネットワーク接続のエラーが発生した場合は再試行を行ったり、データベース接続の失敗時には再接続を試みたりすることが考えられます。 -
例外を無視する理由を明確にする
例外を無視する必要がある場合でも、その理由をコメントで明確にすることが重要です。
無視する理由をコードに残しておけば、後からコードを見たときにその判断が正当であったかどうかを確認できます。
例外を無視してもよい場合の例
例外を無視してもよい場合もありますが、その場合でも必ず理由をコメントで記述しておくことが大切です。
例えば、ファイルを閉じるときに発生した例外を無視することは一般的です。
もしファイルを閉じる際にエラーが発生しても、すでに必要なデータを読み取っていれば、プログラムにとって大きな問題にはならないからです。
とはいえ、その理由を明確にしておくことは、後でコードを確認したときに理解しやすくします。
try {
fileInputStream.close();
} catch (IOException ignoredError) {
// ファイルのクローズが失敗しても問題ないので無視する
}
このコードでは、ファイルを閉じる操作が失敗してもそれがプログラムの流れに影響しない場合に例外を無視しています。
しかし、コメントでその理由を記載することで、後からコードを見た開発者がその判断を理解できるようにしています。
例外処理の具体例
実際のプログラムでよく見られる例外処理の例を紹介します。
以下は、タイムアウトが発生した場合にデフォルトの値を使用する例です。
もし計算が1秒以内に完了しなければ、デフォルト値を返すようにしています。
Future<Integer> futureTask = executor.submit(() -> calculateValue());
int result = 10; // デフォルト値
try {
result = futureTask.get(1L, TimeUnit.SECONDS);
} catch (TimeoutException | ExecutionException ignoredError) {
// 計算結果を取得できない場合、デフォルトの値を使う
}
このコードでは、futureTask.get
がタイムアウトを起こす可能性があります。
そのため、TimeoutException
や ExecutionException
が発生した場合には、デフォルト値(この場合は 10
)を使うという処理を行っています。
このように、例外が発生した場合に何をすべきかを事前に設計し、その処理をコードに組み込むことで、システム全体の安定性を高めることができます。
最後に
例外処理は、プログラムが正常に動作し続けるために不可欠な要素です。
例外を無視せず、適切に処理することで、エラー発生時にも安定した動作を保つことができます。
これらを意識し、より堅牢で信頼性の高いプログラムを書くことを心がけましょう!