1.1 在 Kotlin 中抛出和捕获异常
- Kotlin 中的异常处置惩罚类似于 Java 和许多其他语言中的处置惩罚方式
- 函数可以正常完成,也可以在发生错误时抛出异常
- 函数的调用者可以捕获异常并举行处置惩罚
- 可以使用 throw 关键字抛出异常
- <1> 在本例中,表示调用函数提供一个无效的百分比值
- Kotlin 没有 new 关键词, 创建异常实例也是如此
- if (percentage !in 0..100) { // <1>
- throw IllegalArgumentException( // <1>
- "A percentage value must be between 0 and 100: $percentage"
- )
- }
复制代码
- 在 Kotlin 中,throw 结构是一个表达式
- <1> throw 是一个表达式, 可作为其他表达式的一部分使用
- 假如条件满足, 程序将正常运行
- 并用 number 初始化 percentage 变量
- 否则, 程序将抛出异常, 变量不会被初始化
- 关于表达式与语句的区别–传送门
- val percentage =
- if (number in 0..100)
- number
- else
- // <1>
- throw IllegalArgumentException("A percentage value must be between 0 and 100: $number"
- )
复制代码 1.1.1 处置惩罚异常和从错误中恢复: try、catch 和 finally
- 试图从错误中恢复,而不是抛出异常
- 可以使用带有 catch 和 finally 子句的 try 结构来处置惩罚异常
- <1> 它从 BufferedReader 中读取一行文本,尝试将其分析为一个数字
- 假如该行不是一个有用的数字则返回null
- 反之是有用数字, 则会返回分析后的数值
- <2> 在 Kotlin 中, 您无法明确指定函数可以抛出的异常
- import java.io.BufferedReader
- import java.io.StringReader
- fun readNumber(reader: BufferedReader): Int? { // <2>
- try {
- val line = reader.readLine() // <1>
- return Integer.parseInt(line) // <1>
- } catch (e: NumberFormatException) {
- return null // <1>
- } finally {
- reader.close()
- }
- }
- fun main() {
- val reader = BufferedReader(StringReader("239")) // <1>
- println(readNumber(reader))
- // 239
- }
复制代码
- 与 Java 的一个重要区别是,Kotlin 没有 throws 子句
- <1> 假如用Java写这个函数,会在函数声明后明确写入throws IOException
- 您需要如许做,因为 Java 的 readLine 和 close 大概会抛出 IOException
- 在 Java 世界中,这是一种需要明确处置惩罚的异常类型
- 假如您调用另一个函数
- 需要处置惩罚它显式指定的异常或声明函数也可以抛出这些异常
- Integer readNumber(BufferedReader reader) throws IOException // <1>
复制代码
- 就像许多其他当代 JVM 语言一样, Kotlin 不区分查抄异常和未查抄异常
- 您可以不指定函数抛出的异常,也可以不处置惩罚任何异常
- 这一计划决策基于 Java 中使用查抄(checked)异常的实践
- 履历表明,Java 规则往往需要大量偶然义的代码来重新抛出或忽略异常
- 这些规则并不能始终如一地保护您免受大概发生的错误的影响
- 例如,在上述示例中,NumberFormatException 并不是一个经过查抄的异常
- 因此,Java编译器不会逼迫您捕获它
- 这是很不幸的,因为无效的输入数据是一种常见的环境,应该从容应对
- 同时,BufferedReader.readLine方法会抛出一个IOException异常
- 假如流关闭,大多数程序都无法采取任何有意义的操作
- 因此捕获流操作方法的IOException异常所需的代码都是模板化的
- 由于这一计划决策,您可以自行决定要处置惩罚或不要处置惩罚哪些异常
- <1> 假如你乐意,完全可以不使用任何 try-catch 结构来实现 readNumber 函数
- 在 Kotlin 中,编译器不会逼迫您处置惩罚异常
- fun readNumber(reader: BufferedReader): Int {
- val line = reader.readLine() // <1>
- reader.close()
- return Integer.parseInt(line)
- }
复制代码
- 那么 Java 的 try-with-resources 呢?
- Kotlin 对此没有任何特殊语法, 它是作为库函数实现的
1.1.2 使用 try 作为表达式
- 到目前为止,你只看到 try 结构作为语句使用
- 但是,由于 try 是一个表达式(就像 if 和 when 一样)
- <1> 利用这一点,将 try 表达式的值赋值给一个变量
- fun readNumber(reader: BufferedReader): Int? {
- val number = try { // <1>
- Integer.parseInt(reader.readLine())
- }catch (e: NumberFormatException) {
- return null
- }finally {
- reader.close()
- }
- }
复制代码
- 值得注意的是,与 if 差别,即使块体只包罗一个表达式,大括号也是不能省略的
- 与其他语句一样,假如主体包罗多个表达式
- 则整个 try 表达式的值就是最后一个表达式的值
- 代码块中的最后一个表达式即为结果–传送门
- 上面示例在 catch 代码块中参加 return 语句
- <1> 假如要继续执行,catch 子句也作为表达式
- 即这里的null作为catch表达式的值赋值给 number 变量
- fun readNumber(reader: BufferedReader): Int? {
- val number = try {
- Integer.parseInt(reader.readLine())
- }catch (e: NumberFormatException) {
- null // <1>
- }
- println("number: $number")
- return number
- }
复制代码
- 假如 try 代码块的执行环境正常,则该代码块中的最后一个表达式就是结果
- 假如捕获异常,相应 catch 代码块中的最后一个表达式也是结果
- 使用 try 作为表达式,可以避免引入额外的中间变量
- 还可以分配回退值(catch作为表达式)或直接从外层函数返回(在catch中return)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |