Javaのthrowsキーワードの使い方とは?例外処理を呼び出し元に渡す基本を解説
生徒
「先生、Javaで例外をメソッドの中じゃなくて、呼び出し元に渡すことってできるんですか?」
先生
「もちろんできますよ。そのときに使うのがthrowsキーワードです。」
生徒
「えっ、throwと何が違うんですか?」
先生
「いい質問ですね。それではthrowsキーワードの基本から実例まで丁寧に解説していきましょう!」
1. Javaのthrowsキーワードとは?
Javaのthrowsキーワードは、メソッドの宣言時に使用し、そのメソッド内で発生する可能性がある例外を、呼び出し元に伝えるために使います。これにより、メソッド内で例外を処理せず、呼び出し側でまとめて例外処理を行うことができます。
Javaの例外処理においては、チェック例外(checked exception)を扱う際に、throwsを使うことが多いです。未処理のチェック例外があると、コンパイルエラーになりますので、throwsで明示することでエラーを防げます。
2. throwとの違いを整理しよう
Java初心者がよく混乱するのがthrowとthrowsの違いです。
- throw:実際に例外を発生させる
- throws:そのメソッドで発生しうる例外を、呼び出し元に伝える
つまりthrowは例外オブジェクトを投げる命令で、throwsはその「投げうる可能性」を宣言するキーワードです。
3. throwsキーワードの基本的な使い方
Javaのthrowsキーワードは、メソッドの定義において使用し、以下のように記述します。
public class ThrowsExample {
public static void main(String[] args) {
try {
readFile();
} catch (Exception e) {
System.out.println("例外をキャッチしました: " + e.getMessage());
}
}
public static void readFile() throws Exception {
throw new Exception("ファイルが見つかりませんでした");
}
}
この例では、readFile()メソッド内で例外を発生させ、それをthrowsで呼び出し元に投げています。呼び出し元のmain()メソッドでtry-catchによりキャッチされ、適切に処理されています。
4. 複数の例外をthrowsで宣言する
Javaでは、複数の例外が発生する可能性がある場合、throwsでカンマ区切りで指定することが可能です。
public static void process() throws IOException, SQLException {
if (new Random().nextBoolean()) {
throw new IOException("IOエラー");
} else {
throw new SQLException("DBエラー");
}
}
このようにIOExceptionとSQLExceptionを同時に宣言できます。呼び出し元では、両方の例外をキャッチして処理する必要があります。
5. throwsが必要なケースとは?
Javaのthrowsキーワードが必要になるのは主にチェック例外です。たとえば、FileReaderなどのファイル操作、SQLExceptionなどのデータベースアクセス処理では、throwsが必須になります。
一方で、実行時例外(unchecked exception)であるNullPointerExceptionやArrayIndexOutOfBoundsExceptionなどは、throwsしなくても構いません。
6. throwsを使うべき場面と設計の考え方
Javaでは、例外処理の責任を明確に分けることが重要です。メソッド内で処理できない例外は、呼び出し元に投げる(throws)のが基本設計方針です。たとえば、ライブラリやAPIのメソッドでは、内部の詳細に依存しないように、例外を呼び出し元に任せることが多いです。
逆に、アプリケーションのエントリーポイント(mainなど)では、try-catchでしっかり例外をハンドリングするべきです。
7. throwsを使うときの注意点
- throwsで宣言した例外は、必ずどこかでcatchする
- throwsが多すぎると、コードが読みにくくなる
- 共通の親クラス(Exceptionなど)でまとめる手もある
例外の種類が多くなると、throws句も長くなり、メソッドの読みやすさが低下します。ExceptionやIOExceptionなど、親クラスにまとめることで、ある程度整理できます。
8. 呼び出し元での例外処理の実例
それでは最後に、throwsで例外を渡した後、呼び出し元でどう処理するかの例を見てみましょう。
public class ThrowsDemo {
public static void main(String[] args) {
try {
riskyOperation();
} catch (IOException e) {
System.out.println("IOエラーが発生しました: " + e.getMessage());
}
}
public static void riskyOperation() throws IOException {
FileReader reader = new FileReader("data.txt");
reader.read();
reader.close();
}
}
ここではFileReaderを使ってファイルを読み込んでいますが、ファイルが存在しない場合はIOExceptionが発生します。これをthrowsで外に渡し、呼び出し元のmainでtry-catchしています。