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 教程。