runCatching は、Kotlin標準ライブラリに用意されている 例外処理を簡潔に書くための関数です。
通常の try-catch の代わりに使うことで、処理の成功・失敗を Result 型として扱うことができます。
この仕組みにより、
- 成功した場合の値
- 失敗した場合の例外
を データとして扱えるようになり、関数型スタイルのコードが書きやすくなります。
runCatchingの基本
runCatching は、ブロック内の処理を実行し、その結果を Result<T> 型で返します。
val result = runCatching {
// 例外が発生する可能性のある処理
}
この関数の特徴は、ブロック内で発生した Throwable を捕捉する点です。
つまり、Exception だけでなく Error や CancellationException なども含めて捕捉されます。
処理結果は次のどちらかになります。
- 成功 →
Result.success(value) - 失敗 →
Result.failure(exception)
Result型とは
runCatching が返す Result<T> は、処理の成功または失敗を表す型です。
成功した場合は値を持ち、失敗した場合は例外を保持します。
Result 型には、結果を扱うための様々なメソッドが用意されています。
代表的なメソッドは次の通りです。
| メソッド | 役割 |
|---|---|
getOrNull() | 成功値を取得(失敗ならnull) |
getOrElse {} | 失敗時に代替値を返す |
getOrThrow() | 失敗時に例外を再スロー |
onSuccess {} | 成功時の処理 |
onFailure {} | 失敗時の処理 |
map {} | 成功値を変換 |
recover {} | 失敗時に回復 |
基本的な使用例
文字列を整数に変換する例
val result = runCatching {
"123".toInt()
}
成功した場合は整数が保持され、失敗した場合は NumberFormatException が保持されます。
成功時の処理
onSuccess
成功した場合に処理を実行できます。
runCatching {
"123".toInt()
}.onSuccess {
println("成功: $it")
}
ここで it は成功した値です。
getOrNull
成功値だけ取得する場合に使います。
val number = runCatching {
"123".toInt()
}.getOrNull()
処理が失敗した場合は null が返ります。
失敗時の処理
onFailure
失敗した場合の処理を定義できます。
runCatching {
"abc".toInt()
}.onFailure {
println("エラー: ${it.message}")
}
it には例外オブジェクトが渡されます。
getOrElse
失敗した場合のデフォルト値を指定できます。
val number = runCatching {
"abc".toInt()
}.getOrElse {
0
}
この例では変換が失敗した場合、0 が返ります。
成功値の変換(map)
成功した場合の値を変換できます。
val result = runCatching {
"123".toInt()
}.map {
it * 2
}
ただし重要なポイントとして、map の変換処理内で例外が発生した場合、その例外は Resultに包まれず再スローされます。
例外も Result に包みたい場合は mapCatching を使います。
val result = runCatching {
"123".toInt()
}.mapCatching {
it / 0
}
この場合、例外は Result.failure として保持されます。
失敗時の回復(recover)
recover は失敗した場合に代替値を返します。
val result = runCatching {
"abc".toInt()
}.recover {
0
}
この例では、失敗した場合に 0 が返されます。
ただし recover 内で例外が発生した場合、その例外は再スローされます。
例外も Result に包みたい場合は recoverCatching を使用します。
val result = runCatching {
"abc".toInt()
}.recoverCatching {
0
}
try-catchとの違い
通常の例外処理は次のように書きます。
val number = try {
"123".toInt()
} catch (e: Exception) {
0
}
runCatching を使うと次のようになります。
val number = runCatching {
"123".toInt()
}.getOrElse { 0 }
runCatching を使うことで、
- 処理をチェーンで書ける
- 成功・失敗の処理を分離できる
- 関数型スタイルのコードになる
といったメリットがあります。
Coroutineでの注意点
runCatching は Throwable を捕捉するため、Coroutine のキャンセルで使われる CancellationException も捕まえてしまう可能性があります。
その結果、Coroutine のキャンセルが正しく伝播しないことがあります。
そのため、Coroutineで使用する場合は注意が必要です。
runCatchingの拡張版
runCatching には、レシーバ付きの拡張関数もあります。
val result = user.runCatching {
getName()
}
この形式では this をレシーバとしてブロック内で利用できます。
runCatchingのメリット
主な利点は次の通りです。
- 例外処理を簡潔に書ける
- 成功と失敗を
Resultとして扱える - チェーン処理が可能
- API通信やパース処理などで便利
まとめ
runCatching は、例外処理を Result 型として扱うための関数です。
主な特徴は次の通りです。
- 処理結果を
Resultとして返す Throwableを捕捉する- 成功・失敗を関数チェーンで処理できる
map/recoverなどで結果を変換できる- 例外を包む変換には
mapCatching/recoverCatchingを使う
Kotlinでは、例外処理を単なる制御フローとして扱うのではなく、値として扱う設計が重視されておりrunCatching はその代表的な機能です。
以上、KotlinのrunCatchingについてでした。
最後までお読みいただき、ありがとうございました。










