Kotlinのrethrow(例外の再送出)の使い方を初心者向けに解説!catchで処理してから再度スローする方法
生徒
「Kotlinのcatchってエラーを捕まえて終わりですよね?」
先生
「たしかに普通はそうですが、一度処理してから再び投げることもできるんですよ。それをrethrow(リスロー)といいます。」
生徒
「えっ、投げるってどういう意味ですか?」
先生
「プログラムに『このエラーを上の処理に戻して!』と伝えることを“投げる”と言います。詳しく説明しますね!」
1. Kotlinのrethrow(再送出)とは?
Kotlin(コトリン)でtry-catchを使うと、エラー(例外)を捕まえて安全に処理できます。
ただし、catchの中で一度ログを残したり、ユーザーに通知を表示したりした後に、「このエラーはさらに上のレベルで扱ってほしい」という場面もあります。
そんなときに使うのがrethrow、つまり例外の再送出です。
2. 例外を再送出(rethrow)する基本構文
例外を再送出するには、catchの中でthrow eと書くだけです。ここでのeはcatchで受け取った例外オブジェクトです。
以下のコードで確認してみましょう。
fun riskyOperation() {
try {
val number = "abc".toInt()
} catch (e: NumberFormatException) {
println("ログ出力:変換に失敗しました")
throw e // 例外を再送出
}
}
このコードでは、まずtoInt()で失敗し、catchでログを出力。その後、throw eで再び例外を上の処理に投げ返しています。
3. 実行例:上位の関数で再送出された例外をキャッチする
例外を再送出すると、呼び出した元の関数にそのエラーが戻ってきます。実際にやってみましょう。
fun riskyOperation() {
try {
val number = "abc".toInt()
} catch (e: NumberFormatException) {
println("ログ:エラー発生 ${e.message}")
throw e
}
}
fun main() {
try {
riskyOperation()
} catch (e: NumberFormatException) {
println("main関数でエラーをキャッチしました")
}
}
ログ:エラー発生 For input string: "abc"
main関数でエラーをキャッチしました
riskyOperation内でエラーをthrowして、それをmain関数が受け止めています。これが例外の再送出(rethrow)の基本的な流れです。
4. なぜrethrowが必要なのか?
例外を再送出する理由は、最終的な判断をもっと上の処理で行いたいからです。
たとえば、下の処理ではログだけ残して、画面にエラーメッセージを出すのは上の処理に任せたいときなどです。
また、大きなアプリでは、最上位でまとめて例外を処理する設計がよく使われています。
5. rethrowを使うときの注意点
必ずthrowするのは例外(Exception)でなければなりません。
catchで受け取ったe以外のものをthrowしようとすると、コンパイルエラーになります。
また、再送出した例外がどこでもキャッチされなければ、プログラムはエラーで終了します。そのため、上のレベルでもtry-catchを書いておくのが安心です。
6. rethrowの実用例:ファイル処理の中で使う
たとえば、ファイルを開くときにエラーが出る可能性がある場合、ログを残してから再送出する例です。
fun readFile() {
try {
throw java.io.IOException("ファイルが見つかりません")
} catch (e: java.io.IOException) {
println("エラーログ:${e.message}")
throw e
}
}
fun main() {
try {
readFile()
} catch (e: java.io.IOException) {
println("mainでファイルエラーを処理しました")
}
}
エラーログ:ファイルが見つかりません
mainでファイルエラーを処理しました
このように、rethrowはエラーログを残しつつ、処理を上位に任せるためのテクニックとして使えます。
7. Kotlinの例外処理とrethrowを正しく使い分けよう
Kotlinでは、エラーをその場で処理するだけでなく、throwを使って再び投げることで、柔軟にエラーハンドリングができるようになります。
初心者でも使えるように、まずはログ出力 → throw → 上位でcatch、という流れを理解しておくと安心です。