Kotlin throw 关键字
最后修改于 2025 年 4 月 19 日
Kotlin 的异常处理系统允许使用 throw 关键字显式抛出异常。本教程将通过实际示例深入探讨 throw 关键字。
基本定义
Kotlin 中的 throw 关键字用于显式抛出异常。当抛出异常时,程序的正常流程会被中断。异常会沿调用栈向上冒泡,直到被 try-catch 块捕获。
抛出内置异常
throw 最简单的用法是抛出标准的 Kotlin 异常。此示例演示了抛出 IllegalArgumentException。
package com.zetcode
fun checkAge(age: Int) {
if (age < 0) {
throw IllegalArgumentException("Age cannot be negative")
}
println("Age is valid: $age")
}
fun main() {
try {
checkAge(-5)
} catch (e: IllegalArgumentException) {
println(e.message) // Output: Age cannot be negative
}
}
在这里,当年龄参数为负数时,我们抛出一个 IllegalArgumentException。异常在 main 函数中被捕获,并打印其消息。这展示了基本的异常抛出和处理。
创建自定义异常
Kotlin 允许通过扩展 Exception 类来创建自定义异常类。此示例展示了如何定义和抛出自定义异常。
package com.zetcode
class InvalidEmailException(message: String) : Exception(message)
fun validateEmail(email: String) {
if (!email.contains("@")) {
throw InvalidEmailException("Invalid email format")
}
println("Email is valid: $email")
}
fun main() {
try {
validateEmail("user.example.com")
} catch (e: InvalidEmailException) {
println(e.message) // Output: Invalid email format
}
}
我们定义了一个自定义的 InvalidEmailException 类,它扩展了 Exception。当电子邮件不包含“@”时,validateEmail 函数会抛出此异常。自定义异常使错误处理更具体。
在表达式中抛出异常
Kotlin 允许将 throw 用作表达式。这使得可以在需要表达式的地方抛出异常,例如在 Elvis 运算符中。
package com.zetcode
fun getLength(str: String?): Int {
return str?.length ?: throw IllegalArgumentException("String cannot be null")
}
fun main() {
try {
println(getLength(null))
} catch (e: IllegalArgumentException) {
println(e.message) // Output: String cannot be null
}
}
这里,throw 被用作 Elvis 运算符表达式的一部分。如果字符串为 null,则抛出异常。这种模式在 Kotlin 中进行空值检查很常见。
重新抛出异常
有时您需要捕获一个异常,执行一些操作,然后重新抛出它。此示例展示了如何在 Kotlin 中重新抛出异常。
package com.zetcode
fun processNumber(str: String) {
try {
val num = str.toInt()
println("Processed number: $num")
} catch (e: NumberFormatException) {
println("Logging error: ${e.message}")
throw e // Rethrow the exception
}
}
fun main() {
try {
processNumber("abc")
} catch (e: NumberFormatException) {
println("Caught rethrown exception") // Output: Caught rethrown exception
}
}
processNumber 函数捕获一个 NumberFormatException,记录它,然后重新抛出它。main 函数捕获重新抛出的异常。这种模式在传播异常之前进行日志记录时很有用。
从 Lambda 抛出异常
Kotlin 中的 Lambda 表达式可以像常规函数一样抛出异常。此示例展示了在 lambda 表达式中抛出异常。
package com.zetcode
fun calculate(operation: (Int, Int) -> Int, a: Int, b: Int): Int {
return try {
operation(a, b)
} catch (e: ArithmeticException) {
println("Calculation error: ${e.message}")
-1
}
}
fun main() {
val result = calculate({ x, y ->
if (y == 0) throw ArithmeticException("Division by zero")
x / y
}, 10, 0)
println(result) // Output: -1
}
传递给 calculate 的 lambda 在尝试除以零时抛出一个 ArithmeticException。异常在 calculate 函数中被捕获。这显示了异常如何从 lambda 传播。
将 throw 与 Nothing 类型一起使用
在 Kotlin 中,throw 具有特殊的类型 Nothing。这意味着它可以在需要任何类型的地方使用。编译器知道在 throw 之后不会继续执行。
package com.zetcode
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}
fun getUser(id: Int): String {
return if (id > 0) {
"User$id"
} else {
fail("Invalid user ID")
}
}
fun main() {
try {
println(getUser(1)) // Output: User1
println(getUser(-1)) // Throws exception
} catch (e: IllegalArgumentException) {
println(e.message) // Output: Invalid user ID
}
}
fail 函数返回 Nothing,允许它在 getUser 中需要 String 的地方使用。编译器知道 else 分支将抛出异常,并且不会正常返回。
异常处理最佳实践
- 对异常情况使用异常:不要将异常用于正常的流程控制。
- 更喜欢特定的异常:抛出最适合错误条件的特定异常。
- 提供有意义的消息:在异常消息中包含有用的信息。
- 记录抛出的异常:使用 Kotlin 的文档来记录函数可能抛出的异常。
- 考虑替代方案:对于可恢复的错误,请考虑使用密封类或结果类型而不是异常。
来源
本教程深入探讨了 Kotlin 的 throw 关键字,展示了如何抛出内置和自定义异常。我们探讨了各种场景,包括表达式抛出、重新抛出和 Nothing 类型。适当的异常处理使您的代码更健壮且易于维护。
作者
列出 所有 Kotlin 教程。