Kotlin 抛出和捕获异常(十一)

海哥  金牌会员 | 2024-11-28 16:46:16 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 881|帖子 881|积分 2643

1.1 在 Kotlin 中抛出和捕获异常


  • Kotlin 中的异常处置惩罚类似于 Java 和许多其他语言中的处置惩罚方式

    • 函数可以正常完成,也可以在发生错误时抛出异常
    • 函数的调用者可以捕获异常并举行处置惩罚

      • 假如不捕获,异常会被重新抛出到堆栈的更上层


  • 可以使用 throw 关键字抛出异常

    • <1> 在本例中,表示调用函数提供一个无效的百分比值

      • Kotlin 没有 new 关键词, 创建异常实例也是如此


  1. if (percentage !in 0..100) {                 // <1>
  2.     throw IllegalArgumentException(          // <1>
  3.         "A percentage value must be between 0 and 100: $percentage"
  4.     )
  5. }
复制代码

  • 在 Kotlin 中,throw 结构是一个表达式

    • <1> throw 是一个表达式, 可作为其他表达式的一部分使用

      • 假如条件满足, 程序将正常运行

        • 用 number 初始化 percentage 变量

      • 否则, 程序将抛出异常, 变量不会被初始化
      • 关于表达式与语句的区别–传送门


  1. val percentage =
  2.     if (number in 0..100)
  3.         number
  4.     else
  5.         // <1>
  6.         throw IllegalArgumentException("A percentage value must be between 0 and 100: $number"
  7. )
复制代码
1.1.1 处置惩罚异常和从错误中恢复: try、catch 和 finally


  • 试图从错误中恢复,而不是抛出异常

    • 可以使用带有 catch 和 finally 子句的 try 结构处置惩罚异常
    • <1> 它从 BufferedReader 中读取一行文本,尝试将其分析为一个数字

      • 假如该行不是一个有用的数字返回null
      • 反之是有用数字, 则会返回分析后的数值

    • <2> 在 Kotlin 中, 您无法明确指定函数可以抛出的异常

  1. import java.io.BufferedReader
  2. import java.io.StringReader
  3. fun readNumber(reader: BufferedReader): Int? {          // <2>
  4.     try {
  5.         val line = reader.readLine()                    // <1>
  6.         return Integer.parseInt(line)                   // <1>
  7.     } catch (e: NumberFormatException) {
  8.         return null                                     // <1>
  9.     } finally {
  10.         reader.close()
  11.     }
  12. }
  13. fun main() {
  14.     val reader = BufferedReader(StringReader("239"))   // <1>
  15.     println(readNumber(reader))
  16.     // 239
  17. }
复制代码

  • 与 Java 的一个重要区别是,Kotlin 没有 throws 子句

    • <1> 假如用Java写这个函数,会在函数声明后明确写入throws IOException

      • 在 Java 中,查抄异常是方法签名的一部分

    • 您需要如许做,因为 Java 的 readLine 和 close 大概会抛出 IOException

      • 这是一种经过查抄的异常



    • 在 Java 世界中,这是一种需要明确处置惩罚的异常类型

      • 必须声明您的函数显式指定全部经过查抄的异常*

    • 假如您调用另一个函数

      • 需要处置惩罚它显式指定的异常声明函数也可以抛出这些异常


  1. Integer readNumber(BufferedReader reader) throws IOException   // <1>
复制代码

  • 就像许多其他当代 JVM 语言一样, Kotlin 不区分查抄异常和未查抄异常

    • 您可以不指定函数抛出的异常,也可以不处置惩罚任何异常

      • 这一计划决策基于 Java 中使用查抄(checked)异常的实践

    • 履历表明,Java 规则往往需要大量偶然义的代码重新抛出或忽略异常

      • 这些规则并不能始终如一地保护免受大概发生的错误的影响

    • 例如,在上述示例中,NumberFormatException 并不是一个经过查抄的异常

      • 因此,Java编译器不会逼迫您捕获它

        • 你可以在运行时轻松地看到异常发生


      • 这是很不幸的,因为无效的输入数据是一种常见的环境,应该从容应对

      • 同时,BufferedReader.readLine方法抛出一个IOException异常

        • 这是一个经过查抄的异常,需要加以处置惩罚



    • 假如流关闭,大多数程序都无法采取任何有意义的操作

      • 因此捕获流操作方法的IOException异常所需的代码都是模板化



  • 由于这一计划决策,您可以自行决定要处置惩罚不要处置惩罚哪些异常

    • <1> 假如你乐意,完全可以不使用任何 try-catch 结构来实现 readNumber 函数

      • 在 Kotlin 中,编译器不会逼迫您处置惩罚异常


  1. fun readNumber(reader: BufferedReader): Int {
  2.     val line = reader.readLine()                     // <1>
  3.     reader.close()
  4.     return Integer.parseInt(line)
  5. }
复制代码

  • 那么 Java 的 try-with-resources 呢?

    • Kotlin 对此没有任何特殊语法, 它是作为库函数实现的

1.1.2 使用 try 作为表达式


  • 到目前为止,你只看到 try 结构作为语句使用

    • 但是,由于 try 是一个表达式(就像 if 和 when 一样)
    • <1> 利用这一点,将 try 表达式的值赋值给一个变量

  1. fun readNumber(reader: BufferedReader): Int? {
  2.     val number = try {                                  // <1>
  3.         Integer.parseInt(reader.readLine())
  4.     }catch (e: NumberFormatException) {
  5.         return null
  6.     }finally {
  7.         reader.close()
  8.     }
  9. }
复制代码

  • 值得注意的是,与 if 差别,即使块体只包罗一个表达式,大括号也是不能省略

    • 与其他语句一样,假如主体包罗多个表达式

      • 整个 try 表达式的值就是最后一个表达式的值
      • 代码块中的最后一个表达式即为结果–传送门

    • 上面示例在 catch 代码块中参加 return 语句

      • 因此函数不会在 catch 代码块之后继续执行

    • <1> 假如要继续执行,catch 子句也作为表达式

      • 即这里的null作为catch表达式的值赋值给 number 变量


  1. fun readNumber(reader: BufferedReader): Int? {
  2.     val number = try {
  3.         Integer.parseInt(reader.readLine())
  4.     }catch (e: NumberFormatException) {
  5.         null                                       // <1>
  6.     }
  7.     println("number: $number")
  8.     return number
  9. }
复制代码

  • 假如 try 代码块的执行环境正常,则该代码块中的最后一个表达式就是结果

    • 假如捕获异常,相应 catch 代码块中的最后一个表达式也是结果
    • 使用 try 作为表达式,可以避免引入额外的中间变量

      • 还可以分配回退值(catch作为表达式)或直接从外层函数返回(在catch中return)



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

海哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表