例外処理

例外とは?

プログラム実行時に発生する予期せぬエラーのことです。コンパイル時に文法に問題があるとコンパイルできず、実行することができません。これをコンパイルエラーと言いますが、文法に問題がなくコンパイルできても、実行時にエラーになることがあります。JavaではException(クラス)と言います。

なぜ予期せぬエラーが発生するのか?

データベースやファイル(ハードウェア)のような外部の要因が影響するからです。
  • ファイルの中身がなかったから
  • データベースが立ち上がっていなかったから
などです。

例外処理

例外処理とは?例外が発生してもシステムをダウンさせないようにする対応のことです。予期せぬエラーが発生するとプログラムが強制終了してしまいます。発生した事象に適した対処をするなどが挙げられます。
  • エラーメッセージをユーザーにわかりやすくする
  • セキュリティの観点から内部的なエラーを見せない
try〜catch句を使います。構文は、以下のようになります。
この例では、ファイルを読み込む際の例外処理を行い、finallyブロックでBufferedReaderを閉じてリソースのクローズ漏れを防ぎます。
Java 7以降では、try〜with〜resources構文を使用して、リソースを自動的に閉じることができます。
try〜with〜resources構文は、Java 7以降で導入されたリソース管理のための構文です。この構文を使うと、tryブロック内で使用したリソース(例えば、ファイルやネットワーク接続)が自動的に閉じられます。これにより、リソースのクローズ漏れを防ぎ、コードの可読性と保守性が向上します。

チェック例外と非チェック例外

非チェック例外

コンパイル時にチェックされない例外です。そのため実行時に例外が発生します。この例外はRuntimeExceptionクラスを継承しています。プログラムの中で例外を発生させないようにできる例外です。
  • ArithmeticException
    • 0で割り算すると発生する例外
      • 「0でなければ割り算」はプログラムで対応可能
このコードは以下のように書き換えることができます。
  • NullPointerException(ヌルポ)
    • 変数に実体が保存されていない時に参照すると発生する例外
      • nullチェックすればプログラムで対応可能
このコードは以下のように書き換えることができます。

チェック例外

コンパイル時にチェックされる例外です。実行時に例外が発生する可能性があることを示しています。この例外はRuntimeException以外のExceptionクラスを継承しています。例外処理を記述する必要があります。
  • try 〜 catch
  • 例外処理を実装しないとコンパイルエラーになる例外
主に、データベースやファイル操作などの外部の要因が影響する例外などがそれにあたります。
💡
ファイル操作での例外処理については、Main39.javaやMain40.javaを参照してください。

独自例外

例外クラスは自作することもできます。自作した例外のことを独自例外と言います。エラーにしたい状況で必ずしも例外が発生するとは限らないのです。例えば、入力チェックなどです。その時には例外をthrowさせることもできますが、状況によっては既存の例外に当てはまるものがない場合もあります。
  • 独自例外を使います。
  • 独自の名前のクラスを作ることに意味があります。
  • 独自例外は、ExceptionクラスかRuntimeExceptionクラスを継承して定義します。
独自例外を宣言する構文です。
例外を使う側の処理は、例外クラスのインスタンスを生成して命令文でスローします。
上記のmainメソッドの中の処理を1行で書くと
このようになります。
コンストラクタの章で作成したクラスのコンストラクタで年、月、日の入力チェックをしてみましょう。
mainメソッド側の処理は
-2月でクラスのインスタンスを生成する際に例外が発生します。

独自例外の使い所

  • コンストラクタの中でチェック
    • コンストラクタには戻り値がありません。
      入力チェックした結果をreturnすることができません。
  • ユーザーはコンソールを目にしているとは限らない
    • System.out.printlnメソッドはコンソールに値を出力しますが、ユーザは必ずしもコンソールを目にしているとは限りません。例えばWebアプリケーションの場合は、ブラウザに表示されているHTMLを見ています。
  • 本当に起きた例外なのか?故意に起こした例外なのかわからない
    • 既存の例外を使った場合、本当に起きた例外なのか?故意に起こした例外なのか判断つかないこともあるでしょう。
独自の名前の例外クラスをスローしたことに意味があるのです。