在 Kotlin 中,協程提供了一種更簡潔、更安全的方式來處理異常。協程使用 try-catch
塊來捕獲和處理異常,就像在普通的函數中一樣。但是,協程還提供了一種特殊的異常類型 CoroutineException
,它可以在協程的作用域內拋出和捕獲。
以下是一個使用 Kotlin 協程處理異常的示例:
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
// 啟動一個協程
val result = async {
throw ArithmeticException("division by zero")
// 這里的代碼永遠不會被執行
42
}
// 獲取協程的結果
println(result.await())
} catch (e: ArithmeticException) {
// 捕獲并處理異常
println("Caught exception: ${e.message}")
} catch (e: Exception) {
// 捕獲并處理其他類型的異常
println("Caught exception: ${e.message}")
}
}
在這個示例中,我們使用 async
函數啟動了一個協程,并在其中拋出了一個 ArithmeticException
異常。然后,我們使用 await
函數獲取協程的結果,并使用 try-catch
塊捕獲和處理異常。
注意,當使用 async
函數時,如果協程拋出異常,它將被封裝在 CoroutineException
中。因此,在 catch
塊中,我們需要捕獲 CoroutineException
并從中提取原始異常。我們可以使用 e.cause
屬性來獲取原始異常。
此外,我們還可以使用 CoroutineExceptionHandler
接口來處理協程中的未捕獲異常。這可以在協程的作用域之外進行設置,例如在 runBlocking
或 launch
函數中。以下是一個使用 CoroutineExceptionHandler
的示例:
import kotlinx.coroutines.*
fun main() = runBlocking {
// 創建一個 CoroutineExceptionHandler
val handler = CoroutineExceptionHandler { _, exception ->
println("Caught exception: ${exception.message}")
}
// 啟動一個協程,并將其與 CoroutineExceptionHandler 關聯
val result = async(handler) {
throw ArithmeticException("division by zero")
// 這里的代碼永遠不會被執行
42
}
// 獲取協程的結果
println(result.await())
}
在這個示例中,我們創建了一個 CoroutineExceptionHandler
,并將其傳遞給 async
函數。當協程拋出異常時,處理器將捕獲并處理異常。