编程后端开发工程师

Kotlin 中的异常处理是如何工作的?请描述细节、与 Java 的区别、checked/unchecked 异常的处理、'try'、'catch'、'finally'、传播和最佳实践。请提供示例。

用 Hintsage AI 助手通过面试

答案。

Kotlin 的异常处理(exception handling)与 Java 相似,但有重要区别。Kotlin 使用熟悉的结构 trycatchfinally,但根本区别在于 Kotlin 没有 checked exceptions。这意味着所有异常(运行时错误)都被视为 unchecked — 不需要在函数签名中声明它们,也不需要显式捕获。

主要点:

  • try/catch/finally 块允许捕获和处理异常。finally 块总是会执行,即使抛出了异常。
  • 与 Java 的区别:在 Kotlin 中,所有异常都是 unchecked。这使得语法更简单,但需要对错误处理保持谨慎。
  • Kotlin 支持 try 的 "return value",即 try 可以作为表达式使用,返回结果。
  • 新的习惯用法:建议避免使用 try/catch 来进行流程控制 — 仅在真正异常的情况下使用。
fun parseIntOrNull(str: String): Int? = try { str.toInt() } catch (e: NumberFormatException) { null }

最佳实践:

  • 不要用于控制逻辑(flow control)。
  • 使用 use 进行 "resource management" 以进行自动关闭(例如文件)。
  • 不要用空的 catch 语句来吞噬异常。

让人困惑的问题。

在 Kotlin 中,是否需要在函数签名中指定它所抛出的异常(如 Java 中的 throws)?

正确答案: 不,在 Kotlin 中没有 checked exceptions 的机制。所有异常都是 unchecked。函数签名中没有 throws 的语法(异常 — 注解 @Throws 用于与 Java 的兼容性,仅用于互操作)。

由于对主题细微差别的不理解而导致的实际错误示例。


故事

在项目中,我们将使用 checked exceptions 的 Java 代码(例如 IOException)迁移到 Kotlin。在迁移到 Kotlin 后,开发人员忘记在处理文件时捕获异常 — 应用程序在处理真实文件时开始崩溃,因为没有人处理 IO 错误,以为编译器会像在 Java 中那样发出警告。


故事

团队中的一个成员错误地使用 try/catch 进行流程控制,导致日志解析速度变慢(对于每个无效字符串捕获 NumberFormatException — 在大量数据情况下性能急剧下降)。


故事

在一个为 JVM 的项目中,通过 Kotlin 调用了声明了 checked exceptions (throws) 的 Java 代码。Kotlin 代码没有处理异常,以为 "一切都是 unchecked" — 结果,一个关键错误在生产事故之前没有被注意到。