MST
星途 面试题库

面试题:Kotlin异常处理与协程的交互

在Kotlin协程中,异常处理机制与常规的try - catch有何不同?请详细说明如何在协程中正确处理异常,包括处理不同类型的异常(如取消异常等),并给出相关代码示例及解释。
49.7万 热度难度
编程语言Kotlin

知识考点

AI 面试

面试题答案

一键面试

1. Kotlin协程异常处理机制与常规try - catch的不同

  • 传播方式
    • 常规try - catch:直接在代码块内捕获异常,异常不会跨越函数边界自动传播,除非手动抛出。例如:
fun normalFunction() {
    try {
        // 可能抛出异常的代码
        val result = 1 / 0
    } catch (e: ArithmeticException) {
        // 捕获并处理异常
        println("捕获到算术异常: $e")
    }
}
- **Kotlin协程**:异常在协程作用域内会自动传播,子协程抛出的异常会向上传递给父协程。如果没有在协程内部处理,会导致整个协程作用域取消。例如:
import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        val job = launch {
            throw RuntimeException("子协程异常")
        }
        job.join()
    }.join()
    println("主协程结束")
}
// 这里子协程抛出异常,没有捕获,导致整个协程作用域取消,不会打印 "主协程结束"
  • 处理位置
    • 常规try - catch:在可能抛出异常的代码周围使用try - catch块进行捕获。
    • Kotlin协程:除了在协程内部使用try - catch块,还可以在协程构建器(如launchasync)中通过CoroutineExceptionHandler来处理异常。

2. 在协程中正确处理异常

2.1 使用try - catch块

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        try {
            // 可能抛出异常的代码
            val result = 1 / 0
        } catch (e: ArithmeticException) {
            // 捕获并处理异常
            println("捕获到算术异常: $e")
        }
    }.join()
    println("主协程结束")
}
// 这里在协程内部使用try - catch捕获异常,主协程会正常结束并打印 "主协程结束"

2.2 使用CoroutineExceptionHandler

import kotlinx.coroutines.*

val handler = CoroutineExceptionHandler { _, exception ->
    println("全局捕获异常: $exception")
}

fun main() = runBlocking(handler) {
    launch {
        throw RuntimeException("协程异常")
    }.join()
    println("主协程结束")
}
// 通过CoroutineExceptionHandler在协程作用域级别捕获异常,主协程会正常结束并打印 "主协程结束"

2.3 处理取消异常

取消异常(CancellationException)在协程被取消时抛出。通常不需要手动捕获处理,因为协程取消是正常的流程控制。但如果确实需要区分,可以如下处理:

import kotlinx.coroutines.*

fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } catch (e: CancellationException) {
            println("协程被取消: $e")
            throw e
        }
    }
    delay(500)
    job.cancel()
    job.join()
    println("主协程结束")
}
// 这里手动捕获取消异常,并打印相关信息,主协程会正常结束并打印 "主协程结束"