1. 简介
程序运行过程中,若出现意料之外的情况,就会触发一个 异常(Exception)。像 Kotlin 和 Java 这类语言都内置了丰富的异常类,用于处理常见的错误场景。
但实际开发中,通用异常往往不够用。✅ 我们更需要的是能精准表达业务语义的 自定义异常类,以便更好地定位问题、提升代码可读性。本文将带你掌握在 Kotlin 中如何优雅地创建和使用自定义异常。
💡 为什么需要自定义异常?
想象一下日志里全是IllegalArgumentException
,你根本无法快速判断是参数为空、格式不对还是越界。而InvalidUserInputException
就清晰得多。
2. 创建一个简单的自定义异常
最直接的方式,就是定义一个继承自 Exception
的类:
class MyCustomException(message: String) : Exception(message)
这样就得到了一个可以携带描述信息的异常类型。使用时也很直观:
throw MyCustomException("这是自定义异常的详细说明")
捕获方式与标准异常无异,使用 try-catch
即可:
try {
throw MyCustomException("这是自定义异常的详细说明")
} catch (e: MyCustomException) {
// 在这里处理异常
println("捕获到自定义异常: ${e.message}")
}
📌 注意:捕获时需明确指定异常类型,避免用 catch (e: Exception)
吞掉所有异常,这属于反模式 ❌。
更多 Kotlin 异常处理细节,可参考之前的文章:Kotlin 异常处理详解。
3. 创建功能完整的自定义异常
上面的例子虽然简单,但只覆盖了父类 Exception
的部分构造函数。⚠️ 实际上,Exception
提供了四个重载构造器:
class Exception {
...
constructor() // 无参
constructor(message: String?) // 只有消息
constructor(message: String?, cause: Throwable?) // 消息 + 根源异常
constructor(cause: Throwable?) // 只有根源异常
...
}
如果我们希望自定义异常具备同等能力,就必须全部实现:
class MyCustomException : Exception {
constructor() : super()
constructor(message: String) : super(message)
constructor(message: String, cause: Throwable) : super(message, cause)
constructor(cause: Throwable) : super(cause)
}
✅ 如此一来,这个异常就能在任何标准 Exception
可用的上下文中无缝替换,灵活性大大增强。
4. 使用默认参数减少模板代码
第 3 节的做法虽然完整,但写起来略显啰嗦——四个构造函数全是模板代码。 Kotlin 的 默认参数(default arguments) 特性正好可以解决这个问题:
class CustomException(
message: String? = null,
cause: Throwable? = null
) : Exception(message, cause)
✅ 一行代码搞定!这个简洁版本等价于实现了全部四种构造方式:
CustomException()
→ 无参CustomException("出错了")
→ 带消息CustomException(cause = someException)
→ 带根源CustomException("验证失败", someException)
→ 消息 + 根源
💡 踩坑提醒:
记得把参数声明为可空类型(String?
,Throwable?
),否则无法匹配原始构造函数的签名,会导致调用失败 ❌。
这种写法不仅代码更干净,维护成本也更低,推荐作为首选方案。
5. 总结
在 Kotlin 中创建自定义异常非常简单:
- ✅ 基础需求:继承
Exception
并传入message
- ✅ 完整功能:通过默认参数一键支持所有构造方式,避免冗余代码
合理使用自定义异常,能让错误处理更精确、日志更清晰、调试更高效。
所有示例代码均已上传至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-6