JavaでExceptionを使って例外処理を行う方法を現役エンジニアが解説【初心者向け】
#post_content
テックアカデミーマガジンは受講者数No.1のプログラミングスクール「テックアカデミー」が運営。初心者向けにプロが解説した記事を公開中。現役エンジニアの方はこちらをご覧ください。 ※ アンケートモニター提供元:GMOリサーチ株式会社 調査期間:2021年8月12日~8月16日 調査対象:2020年8月以降にプログラミングスクールを受講した18~80歳の男女1,000名 調査手法:インターネット調査
初心者向けにJavaにおけるExceptionについて解説していきます。
今回は、JavaのExceptionを使った例外処理を解説します。
実務でも、Exceptionを利用した例外処理を実装することがありますので、しっかり学習してください。
なお本記事は、テックアカデミーのJava講座の内容をもとに作成しています。
そもそもJavaについてよく分からないという方は、Javaとは何なのか解説した記事を読むとさらに理解が深まります。
今回はExceptionを使った例外処理について解説しよう。
田島メンター!例外処理というのは何ですか~?
想定外の動作が起こったときの対応を、あらかじめ指定しておくことを言うんだ。まずその予期しない状況、「例外」の具体的な場面について見ていってみようか。
分かりました!
エラーとは
エラーはプログラム動作時に完了できなかった、上手く終了できなかった状態を指します。
プログラムの記述間違いだけでなく、ハードウェアが原因となることもあります。
また、Javaの例外処理については以下のような状態も含みます。
コンパイルエラー
Javaでプログラミングをする上で、最もよく出会うエラーはコンパイルエラー(文法エラー)です。
タイプミスやメソッドの引数の型が異なる、変数に代入する型が違っているというようなケースが多く、コンパイルエラーの場合はそもそも実行できません。
実行時エラー
実行できるプログラムであるものの、何らかの理由でプログラムが異常終了してしまう場合に実行時エラーとなります。
ランタイムエラーと呼ばれることもあり、プログラムが停止した上でクラッシュなどの原因となることもあります。
論理エラー
論理エラーは、実行は問題なく可能であるものの、期待した結果になっていない状態です。
一言でエラー、と言っても様々なものがあるため、混同に注意しましょう。
Exceptionとは
Exceptionは日本語で例外という意味です。
プログラムはあらかじめどういった処理をするのか、という手順を書いたものです。
しかし、状況によっては予期しない事象で正しく処理が行えないこともあります。
そのような予期しない状況を、Javaでは例外(Exception)と呼んでいます。
想定外の事象をなるべく減らすためには、例外が起こった場合に備えて何かしら対応を考えておく、ということが重要です。
そして、例外発生時に対応する処理のことを例外処理(エラーハンドリング)といいます。
例外の種類
Javaで発生する例外(Exception)は、大きく分けて以下の2種類になります。
- 非検査例外
- 検査例外
それぞれの例外(Exception)について解説します。
非検査例外
非検査例外は実行時に起こる例外で、必ずしも対処しなくても良い事象のことです。
なぜ「必ずしも対処しなくてもよい」のかというと、非検査例外の発生要因のほとんどは「仕様の検討漏れ」や「プログラムが仕様通り記述されていない」ことが原因であるためです。
例えば、以下のような場合が該当します。
- Stringの数字をintの整数に変換しようとしたが、そもそも数字ではなかった(NumberFormatException)
- インスタンスがある前提でプログラムは書かれているのに存在しなかった(NullPointerException)
Java では非検査例外の場合は RuntimeException を継承するというルールになっており、上記の例外もそのルールに従っています。
検査例外
検査例外はプログラムが正しく作られていても回避できない例外のことです。
検査例外の例としては、ファイルを開こうとしたが対象のファイルが存在しなかった(FileNotFoundException)などです。
いくらプログラムがファイルの入出力を正しく行うよう記述されていたとしても、プログラム以外の要因でファイルが削除されてしまったり、壊れていたりしてはどうにもなりません。
そのような事態に備え、検査例外を発生させて後述する例外処理を必ず行うように Java の文法レベルで強制されます。
例外処理を行う方法
例外処理は以下の2つの方法があります。
- 自分で例外を処理する
- 自分では処理せず、例外処理を呼び出し元のクラスにthrows する
自分で例外を処理する
自分で例外を処理する場合はtry – catch – finally構文を使用し、finallyブロックは必要に応じて記述しましょう。
例外が発生する可能性のあるメソッドをtryブロックで囲み、catchブロックで処理したい例外を捕らえます。
finallyブロックは、例外が発生してもしなくても共通で行う処理を記述します。
自分では処理せず、例外処理を呼び出し元のクラスにthrows する
例外処理を呼び出し元のクラスに丸投げするには、メソッドのシグニチャにthrows 例外クラス名と記述しましょう。
例外処理の2つの方法について把握できたかい?
はい、try-catchを使う場合とthrowsを使う場合ですね。
次にそれぞれの実際の例を見てみよう。
実際に書いてみよう
自分で例外を処理する場合
今回は、test.txtというファイルを読み込もうとしている処理です。
FileReaderクラスのオブジェクトを生成する時に、対象となるファイルが存在しない場合はFileNotFoundExceptionという例外が発生します。
自分で例外を処理する場合のサンプルコード
FileReader reader = null;
File file = new File("test.txt");
try {
reader = new FileReader(file);
//何かしらファイルの処理が続く
// ...
} catch (FileNotFoundException fnfe) {
// ファイルが見つからなかったときの例外処理
System.out.println(fnfe);
} catch (IOException ioe) {
//それ以外の入出力例外処理
System.out.println(ioe);
} finally {
try {
if(reader != null) {
reader.close();
}
} catch (IOException ioe) {
// closeに失敗したときの例外処理
System.out.println(ioe);
throw ioe;
}
}
System.out.println("ファイル処理完了");
自分で例外を処理する場合の解説
FileNotFoundException
FileNotFoundExceptionという例外が発生する場合は、catchブロックが該当する例外を捕まえ、そのブロック内の処理を行います。
finally
次にfinallyブロックに移り、ファイルのクローズ処理を行います。
finallyブロックは例外が起きなかった場合でも、必ず実行されるブロックです。
また、closeで失敗した場合、IOExceptionという例外が発生します。
ただ、ファイルクローズ時の失敗というのは結構深刻な状況ですので、例外処理としてできることはほとんどないに等しいかと思います。
finallyブロックを抜けると通常通り、以降の処理を続行します。
close周りの処理が非常に複雑です。
実はJava7から try-with-resources構文といって、自動でクローズしてくれる仕組みがあります。
try-with-resources構文を使うと、少し楽に書くことができます。
File file = new File("test.txt");
try(FileReader reader = new FileReader(file)) {
//何かしらファイルの処理が続く
// ...
} catch (FileNotFoundException e) {
// ファイルが見つからなかったときの例外処理
System.out.println(e);
} catch (IOException ioe) {
//それ以外の入出力例外処理
System.out.println(ioe);
}
System.out.println("ファイル処理完了");
自分で例外を処理する場合の表示結果
java.io.FileNotFoundException: test.txt (No such file or directory)
ファイル処理完了
注目すべき点は、ファイル処理完了と例外が発生しても処理を続行できているところです。
このように例外処理を行った後は、通常の処理に戻すことができます。
例外を呼び出し元へthrows する場合
例外を呼び出し元へthrows する場合のサンプルコード
public void read() throws FileNotFoundException, IOException {
File file = new File("test.txt");
FileReader reader = new FileReader(file);
//何かしらファイルの処理が続く
// ...
reader.close();
System.out.println("ファイル処理完了");
}
例外を呼び出し元へthrows する場合の解説
ファイルを読み込むメソッドの名前がreadメソッドだとします。
呼び出し元へthrows する場合は、メソッドのシグニチャにthrows句を記述します。
発生する例外は、以下の結果になります。
FileNotFoundException
IOException
そのため、メソッドシグニチャに以下を追記します。
throws FileNotFoundException, IOException
なお、FileNotFoundExceptionはIOExceptionの子クラスなので、throws IOExceptionのみでも動作自体は問題ないです。
例外を呼び出し元へthrows する場合の表示結果
java.io.FileNotFoundException: test.txt (No such file or directory)
ファイル処理完了
まとめ
以上、Exceptionを使って例外処理を行う方法などについて解説しました。
- エラーとは
- Exceptionとは
- 例外処理を行う方法
どういった場合に扱う処理なのか知っておくと、いざという時役立つでしょう。
入門向けJavaの学習サイトもまとめているので、あわせてご覧ください。
try-catchによる処理とthrowsによる処理、両方の書き方を解説したよ。
コンパイル時ではなく、プログラムの実行中に起こった問題への対応に使うのが例外処理というわけですね。
どのような場面で例外処理が必要になるのか、例外そのものの性質についてもよく調べておこう。
了解です。ありがとうございました!