Kotlin 中的错误处理:try/catch 及其他——从 A 到 Z
错误处理是任何开发者的关键任务之一。在 Kotlin 中,与其他现代语言一样,有几种管理异常情况的方法。在本文中,我们将介绍所有主要方法:从经典的 try/catch 到使用 Result、sealed class 和 Nothing 的高级技术。您将学习如何编写能够正确处理错误的可靠且可读的代码。
1. 经典的 try/catch/finally 块
Kotlin 中基本的异常处理机制是 try/catch 块。它的工作方式与 Java 类似,但有一些改进。在 Kotlin 中,try 是一个表达式,可以返回一个值。
fun parseNumber(input: String): Int? { return try { input.toInt() } catch (e: NumberFormatException) { println("解析错误:${e.message}") null // 出错时返回 null } finally { println("finally 块始终执行") }}
fun main() { val result = parseNumber("123abc") println(result) // null}关键特性:
try可以用作表达式——try或catch块中最后一个表达式的结果成为整个块的结果。finally块在任何情况下都会执行(即使有异常或return)。- Kotlin 没有像 Java 那样的受检异常(checked exceptions)——这简化了代码。
重要的是要记住,过度使用 try/catch 会降低代码的可读性。仅将其用于真正的异常情况,而不是用于控制流。
2. Result 类型与函数式方法
为了更优雅地处理错误,Kotlin 提供了 Result<T> 类型。这是一个密封类,可以是 Success(带有结果)或 Failure(带有异常)。它非常适合函数式风格。
import kotlin.Result
fun divide(a: Int, b: Int): Result<Int> { return try { Result.success(a / b) } catch (e: ArithmeticException) { Result.failure(e) }}
fun main() { val result = divide(10, 0) // 通过 when 处理 when (result) { is Result.Success -> println("结果:${result.value}") is Result.Failure -> println("错误:${result.exception.message}") } // 或者通过方法处理 result.onSuccess { value -> println("成功:$value") } .onFailure { e -> println("失败:${e.message}") } // 转换 val mapped = result.map { it * 2 } // 如果是 failure,则保持为 failure println(mapped)}Result 的优势:
- 明确表明函数可能以错误结束。
- 允许方法链式调用(
map、flatMap、recover)。 - 调用代码中不需要
try/catch。
然而,Result 不适用于存储在集合中或跨协程边界传递——对于这些情况,最好使用 sealed class。
3. 用于详细错误处理的密封类
当需要以不同方式处理不同类型的错误时,sealed class 是理想的选择。您可以创建错误层次结构,并在具有详尽覆盖的 when 中处理它们。
sealed class NetworkResult<out T> { data class Success<T>(val data: T) : NetworkResult<T>() data class NetworkError(val code: Int, val message: String) : NetworkResult<Nothing>() data class Timeout(val timeout