Java入門 STEP19|例外処理を学ぼう

karin@taishi@felmia

例外とは?

プログラムを書いていると、文法は間違っていないのに、実行中に問題が起きることがあります。

例えば、文字列の"100"を数値に変換することはできます。

int number = Integer.parseInt("100");

この場合は、100という数値に変換できます。

では、次の場合はどうでしょうか。

int number = Integer.parseInt("abc");

"abc"を整数に変換することはできません。

このコードを実行すると、途中で例外(Exception)が発生します。

例外とは?

プログラムの実行中に発生する問題のことです。

Javaでは、発生した問題を「例外」として扱い、問題が起きたときの処理を書くことができます。

ルミィ
ルミィ

コードの書き方が合っていても、実行してから問題が起きることがあるんだね!

実際に例外を発生させてみよう

まずは、例外が発生するとどうなるのか確認してみます。

public class ExceptionBasicSample {

    public static void main(String[] args) {

        String text = "abc";

        int number = Integer.parseInt(text);

        System.out.println(number);
    }
}

このコードを実行すると、正常には終了しません。

表示される内容の中には、次のような例外名があります。

NumberFormatException

これは、数値として変換できない文字列を数値に変換しようとしたときなどに発生する例外です。

実際のエラー表示には、このほかにもクラス名や行番号など、原因を調べるための情報が表示されます。

エラーが出たときは、表示された内容を全部読むのが大変でも、まずは例外名や自分が作ったクラスの行番号を確認してみましょう。

try-catchを使ってみよう

例外が発生する可能性がある処理に対して、「例外が起きたらこちらの処理をする」と書くことができます。

そこで使うのがtryとcatchです。

基本的な形を確認します。

try {

    例外が発生する可能性がある処理

} catch (例外の種類 変数名) {

    例外が発生したときの処理

}

実際に先ほどのコードへ追加してみます。

public class TryCatchSample {

    public static void main(String[] args) {

        String text = "abc";

        try {
            int number = Integer.parseInt(text);
            System.out.println(number);
        } catch (NumberFormatException e) {
            System.out.println("数値に変換できませんでした");
        }
    }
}

実行結果

数値に変換できませんでした

今回はInteger.parseInt()でNumberFormatExceptionが発生しました。

すると、その後の、

System.out.println(number);

は実行されず、catchの処理へ移ります。

tryとcatch

tryには、例外が発生する可能性がある処理を書きます。

catchには、指定した例外が発生した場合に行う処理を書きます。

正常な場合はどうなる?

では、textを数値に変換できる文字列へ変更してみます。

public class TryCatchSuccessSample {

    public static void main(String[] args) {

        String text = "100";

        try {
            int number = Integer.parseInt(text);
            System.out.println(number);
        } catch (NumberFormatException e) {
            System.out.println("数値に変換できませんでした");
        }
    }
}

実行結果

100

今回は例外が発生していないため、catchの中には入りません。

つまり、

正常ならtryの処理をそのまま進める

指定した例外が発生したらcatchへ移る

という動きになります。

ルミィ
ルミィ

何も問題がなければ普通に進んで、問題が起きたときだけcatchに入るんだね♪

catchの「e」は何?

ここも最初は分かりにくいところです。

catch (NumberFormatException e)

このeには、発生した例外の情報を持つオブジェクトが入ります。

変数名なので、必ずeでなければならないわけではありません。

ただし、例外を受け取る変数にはeがよく使われます。

例えば、

System.out.println(e.getMessage());

とすると、例外が持っているメッセージを確認できます。

開発中に「何が原因で例外になったのか」を調べるときには、この例外の情報が役立ちます。

複数のcatchを書くこともできる

発生する可能性のある例外が複数ある場合は、catchを複数書くこともできます。

例えば、配列を使ったコードで確認してみましょう。

public class MultipleCatchSample {

    public static void main(String[] args) {

        String[] numbers = {"10", "20", "abc"};

        try {
            int index = 2;
            int number = Integer.parseInt(numbers[index]);

            System.out.println(number);

        } catch (NumberFormatException e) {
            System.out.println("数値に変換できませんでした");

        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("存在しないindexが指定されています");
        }
    }
}

indexが2の場合は、"abc"を数値へ変換しようとするためNumberFormatExceptionが発生します。

一方、例えば、

int index = 5;

に変更すると、配列に存在しないindexを指定することになるため、ArrayIndexOutOfBoundsExceptionが発生します。

このように、発生した例外に合わせて処理を分けることができます。

Exceptionでまとめて受け取ることもできる

Javaでは、さまざまな例外がExceptionというクラスにつながっています。

そのため、

catch (Exception e)

のように書くことで、複数の種類の例外をまとめて受け取ることもできます。

ただし、

「何でもExceptionでcatchしておけばいい」

というわけではありません。

例外によって対応方法が違うのであれば、それぞれに合った例外を指定した方が、何が起きたのかも分かりやすくなります。

とりあえずExceptionにしない

Exceptionを使えば多くの例外をまとめて受け取れます。

ただし、どんな例外が起きる可能性があるのか分かっている場合は、NumberFormatExceptionなど、必要な例外を指定することも大切です。

finallyとは?

try-catchには、さらにfinallyを付けることができます。

public class FinallySample {

    public static void main(String[] args) {

        String text = "abc";

        try {
            int number = Integer.parseInt(text);
            System.out.println(number);

        } catch (NumberFormatException e) {
            System.out.println("数値に変換できませんでした");

        } finally {
            System.out.println("処理を終了します");
        }
    }
}

実行結果

数値に変換できませんでした
処理を終了します

finallyは、基本的に例外が発生した場合でも、発生しなかった場合でも実行される処理を書く場所です。

ファイルやデータベースなど、使い終わったものを閉じる処理で見かけることがあります。

ただし、現在のJavaでは別の書き方が使われることもあります。

このSTEPでは、まず「try-catchにはfinallyを付けることもできる」というところまで知っておけば大丈夫です。

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

Javaの例外を学んでいると、「チェック例外」と「非チェック例外」という言葉が出てきます。

ここでは細かいクラス構造を暗記する必要はありません。

まずは違いを確認しておきましょう。

チェック例外

チェック例外は、コンパイル時に例外への対応が確認される例外です。

例外が発生する可能性がある処理に対して、try-catchなどの対応が必要になります。

例えば、ファイルを扱う処理などで登場します。

非チェック例外

非チェック例外は、try-catchを書いていなくてもコンパイルできる例外です。

今回使った、

NumberFormatException

や、

ArrayIndexOutOfBoundsException

はこちらに含まれます。

プログラムの書き方や、渡された値によって発生することがあります。

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

チェック例外
→ コンパイル時に例外への対応が確認される

非チェック例外
→ try-catchがなくてもコンパイルできる

最初はこの違いを押さえておけば大丈夫です。

try-catchを書けば安心、ではない

例外処理を覚えると、エラーが起きそうなところを全部try-catchで囲みたくなるかもしれません。

ただ、例外が発生しないように事前に確認できるものまで、すべてtry-catchに任せる必要はありません。

また、

catch (Exception e) {
}

のように、例外が起きたのに何もしない書き方をすると、問題が起きていること自体に気づきにくくなります。

実際の開発では、ログへ記録したり、利用者へメッセージを表示したり、その処理を中止したりと、例外が起きたあとにどうするのかまで考えることが大切です。

ルミィ
ルミィ

例外を隠すためのcatchじゃなくて、起きたあとにどうするかを決めるために使うんだね!

よくある間違い

tryの中に何でも入れてしまう

tryの範囲が必要以上に大きいと、どの処理で例外が発生する可能性があるのか分かりにくくなります。

まずは、例外が発生する可能性のある処理がどこなのかを意識してみましょう。

catchする例外を間違える

Integer.parseInt("abc");

で発生するのはNumberFormatExceptionです。

別の例外をcatchしても、そのcatchでは処理できません。

エラーが表示されたら、例外名を確認する習慣を付けておくと原因を探しやすくなります。

catchの中を空にする

catch (Exception e) {

}

これでは例外が発生しても何も表示されないため、問題に気づきにくくなります。

学習中でも、まずはメッセージを表示するなど、例外が発生したことを確認できるようにしておきましょう。

STEP19のまとめ

STEP19のポイント

  • 例外はプログラムの実行中に発生する問題
  • tryに例外が発生する可能性のある処理を書く
  • catchで例外が発生した場合の処理を書く
  • 例外にはNumberFormatExceptionなど、それぞれ名前がある
  • catchは複数書くことができる
  • Exceptionでまとめて受け取ることもできる
  • finallyは例外の有無にかかわらず行いたい処理に使える
  • 例外にはチェック例外と非チェック例外がある
  • 例外が発生したときは、まず例外名や発生した場所を確認する
  • 例外をただ無視するのではなく、その後どうするかを考える

例外処理では、try-catchの書き方だけ覚えるのではなく、「何が起きたのかを確認して、その場合にどうするのかを考える」ことが大切です。

ルミィ
ルミィ

STEP19クリア!
エラー表示も怖がらずに、まずは例外の名前を探してみればいいんだね♪

次のSTEPへ

次のSTEPでは、ここまで学んできたJavaの基礎を組み合わせて、実際に1つのプログラムを作ってみます。

これまで、

  • 変数や条件分岐
  • ループやメソッド
  • 配列やList・Map
  • クラスやカプセル化
  • 継承やオーバーライド
  • 例外処理

など、Javaを書くために必要な基本を少しずつ学んできました。

それぞれを個別に覚えるだけでなく、実際のプログラムでは複数の仕組みを組み合わせて使います。

最後は、これまで覚えたことを振り返りながら、Javaのプログラムを完成させてみましょう。

→ STEP20「Javaの基礎を使ってプログラムを作ろう」

学習内容を確認したいときは、Java入門の一覧から各STEPを確認できます。

→ Java入門|初心者が基礎から学べるJava学習ガイド

記事URLをコピーしました