Java
 Computer >> コンピューター >  >> プログラミング >> Java

Javaで例外をスローする方法!throwとthrowsキーワードの使い方を徹底解説

例外(Exception)とは、プログラムの実行中に発生する予期しないイベントのことです。コードが例外に遭遇すると、プログラムの処理フローはそこで中断されてしまいます。

Javaでコーディングする際には、例外を適切に処理することが非常に重要です。適切に処理しないと、実行時にプログラムが強制終了し、エンドユーザーの体験に悪影響を及ぼす可能性があります。

そこで活躍するのが「throw」と「throws」という2つのキーワードです。これらはJavaで例外を扱うために用意されたキーワードであり、本記事では具体例を挙げながら、それぞれの使い方を詳しく解説していきます。

Javaにおける例外とは

Javaでは、プログラムの流れに影響を与えるイベントとして、「エラー」と「例外」の2種類が存在します。

1つ目は「エラー」です。これはJava仮想マシン(JVM)上で発生する問題、たとえばメモリリーク、システムメモリの枯渇、ライブラリの互換性の問題などを指します。エラーが発生した場合、プログラムが復旧できる可能性は低く、通常は開発者が制御できる範囲外であるため、Javaではエラーはハンドリングしません。

2つ目が「例外」です。例外はコード内で捕捉(キャッチ)して処理することが可能です。例外が発生すると、例外に関する情報を持ったオブジェクトが生成され、それを利用して「例外発生時に何をすべきか」をコードに指示できます。

例外が発生する主な原因には、以下のようなものがあります:

  • コード内のバグ(誤り)
  • 存在しないファイルを開こうとした場合
  • 無効なユーザー入力
  • ネットワーク接続の切断

例外処理を始める前に、押さえておきたい例外の種類が2つあります:

  • 非検査例外(Unchecked Exception):実行時(ランタイム)にチェックされる例外です。例としてはArithmeticExceptionArrayIndexOutOfBoundsExceptionなどが挙げられます。
  • 検査例外(Checked Exception):コンパイル時にチェックされる例外です。例としてはIOExceptionInterruptedExceptionなどが挙げられます。

基本的には、コード内で処理すべきなのは検査例外です。非検査例外の多くは、コードの予期しない動作ではなく、プログラミングミスによって引き起こされるものだからです。

Javaのthrowsキーワード

Javaのthrowsキーワードは、あるコードブロックで発生しうる例外の型を宣言するために使われます。throws句の基本構文は以下の通りです:

accessModifier return functionName() throws Exception1, Exception2 {
   // 実行するコード
}

具体例で見てみましょう。映画館向けのプログラムを作成しているとします。このプログラムは、16歳以上限定の映画に来場する顧客の年齢をチェックします。顧客が16歳未満であれば入場を許可せず、16歳以上であれば入場を許可する仕組みです。

以下は、顧客の年齢をチェックし、16歳未満の場合にArithmeticExceptionをスローするコードです:

class Main {
	public static void verifyAge(int age) throws ArithmeticException {
		if (age < 16) {
			throw new ArithmeticException("This customer is not old enough to see the movie.");
		} else {
			System.out.println("This customer is old enough to see the movie.");
		}
	}

	public static void main(String[] args) {
		verifyAge(14);
	}
}

このコードを実行すると、次の出力が得られます:

Exception in thread "main" java.lang.ArithmeticException: This customer is not old enough to see the movie.

    at Main.verifyAge(Main.java:4)

    at Main.main(Main.java:11)

このプログラムでは、mainメソッドで指定した年齢パラメータが14に設定されています。14は16未満であるため、verifyAge()メソッドが実行されると条件式age < 16がtrueと評価され、ArithmeticExceptionがスローされます。

ここで、throwsキーワードはverifyAge()メソッドが返す可能性のある例外の型を定義するために使われ、throwキーワードは実際にプログラム内で例外をスローするために使われています。両者の役割の違いをしっかり区別しておきましょう。

Javaのthrowキーワード

Javaのthrowキーワードは、コード内で単一の例外をスローするために使用します。throwキーワードの後ろには、例外発生時にプログラム内でスローされるオブジェクトを記述します。

throwキーワードの構文は以下の通りです:

throw throwObject;

それでは、throwステートメントを使ってJavaで例外を処理する具体例をいくつか見ていきましょう。

検査例外をスローする

プログラム内でIOExceptionが発生した際に「This file does not exist.(このファイルは存在しません)」というメッセージを表示したいとします。IOExceptionは検査例外なので、throwキーワードを使って適切に処理する必要があります。以下がそのコードです:

import java.io.*;

class Main {
	public static void getFile() throws IOException {
		throw new IOException("This file does not exist.");
	}
	
	public static void main(String[] args) {
		try {
			getFile();
		} catch (IOException error) {
			System.out.println(error.getMessage());
		}
	}
}

このコードを実行すると、次の出力が得られます:

This file does not exist.

コードを分解して確認しましょう。まず、ファイルを扱うプログラムで必要となるjava.ioライブラリをインポートします。次に、プログラムのコードを格納するMainクラスを作成します。

Mainクラスの中では、IOExceptionをスローするgetFile()メソッドを定義しています。このメソッドは、「This file does not exist.」というメッセージとともにIOExceptionをスローします。

さらにmainメソッド内では、getFile()メソッドの実行を試みるtry/catchブロックを作成しています。IOExceptionが発生した場合にはcatchブロック内のコードが実行され、IOExceptionのメッセージがコンソールに出力されます。その結果、先ほど宣言したメッセージである「This file does not exist.」が表示されるのです。

非検査例外をスローする

続いて、プログラムが文字列に存在しないインデックス値へアクセスしようとした場合に、StringIndexOutOfBoundsExceptionをスローしたいケースを考えてみます。その場合、以下のようなコードを使用できます:

class Main {
	public static void outOfBounds() {
		throw new StringIndexOutOfBoundsException("This index value is invalid.");
	}

	public static void main(String[] args) {
		outOfBounds();
	}
}

このコードの内容を順番に見ていきましょう。まず、プログラムのコードを格納するMainクラスを宣言しています。

次に、実行されるとStringIndexOutOfBoundsExceptionをスローするoutOfBounds()メソッドを作成しています。この例外には「This index value is invalid.」というメッセージが付随します。最後に、mainメソッド内でoutOfBounds()メソッドを呼び出しており、実行結果は以下のようになります:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: This index value is invalid.

    at Main.outOfBounds(Main.java:3)

    at Main.main(Main.java:7)

この例では非検査例外をスローしました。前述の通り、通常は必須ではありませんが、構文の理解を深めるためにあえてスローしてみました。

まとめ

検査例外を適切に処理することは、Javaで保守性の高いコードを書くための重要なスキルです。Javaでは、throwとthrowsキーワードを使って例外をスローし、ハンドリングします。

本記事では、Javaにおけるthrowとthrowsキーワードの使い方を、理解を助ける具体的なサンプルコードとともに解説しました。この記事の内容をマスターすれば、あなたもプロのようにJavaで例外をスローし、適切に処理できるようになるはずです!

  1. JavaでArrayListを初期化する方法|Arrays.asList()の使い方を解説

    Javaでリストを初期化する際には、Arrays.asList()メソッドとArrayListクラスが活用されます。通常のListインターフェースは直接オブジェクトを生成できないため、空のリストを作成するにはArrayListクラスが必要です。さらに、Arrays.asList()メソッドを使えば、初期値を持つArrayListを簡単に初期化できます。 ArrayListとは?Javaにおける基本的な役割 ArrayListの初期化とは、あらかじめ用意した値のセットをリストに代入する処理のことです。JavaでArrayListを扱うには、その初期化方法を理解しておくことが不可欠です。 ここで

  2. 【初心者向け】C++の例外処理の仕組みを徹底解説!try・catch・throwの基本から独自例外の作成まで

    C++における例外処理(Exception Handling)とは、プログラムの実行中に発生するエラー(ランタイムエラー)を適切に処理するための仕組みです。例外とは、実行時に送出されるイベントのことを指し、C++ではすべての標準例外が std::exception クラスを基底クラスとして定義されています。 もし例外を捕捉しなければ、プログラムは例外メッセージを出力した後に異常終了してしまいます。例外はハンドリング可能なランタイムエラーであり、適切に処理することでプログラムの堅牢性を大きく向上させることができます。 標準例外クラスの階層構造 C++標準では、例外は <exception&