KotlinのrunCatchingについて

採用はこちら

runCatching は、Kotlin標準ライブラリに用意されている 例外処理を簡潔に書くための関数です。

通常の try-catch の代わりに使うことで、処理の成功・失敗を Resultとして扱うことができます。

この仕組みにより、

  • 成功した場合の値
  • 失敗した場合の例外

データとして扱えるようになり、関数型スタイルのコードが書きやすくなります。

目次

runCatchingの基本

runCatching は、ブロック内の処理を実行し、その結果を Result<T> 型で返します。

val result = runCatching {
    // 例外が発生する可能性のある処理
}

この関数の特徴は、ブロック内で発生した Throwable を捕捉する点です。

つまり、Exception だけでなく ErrorCancellationException なども含めて捕捉されます。

処理結果は次のどちらかになります。

  • 成功 → 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での注意点

runCatchingThrowable を捕捉するため、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についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次