Kotlin異常處理

異常

異常類

Kotlin 中所有異常類都是 Throwable 類的子孫類。
每個異常都有消息、堆棧回溯信息和可選的原因。

使用 throw{: .keyword }-表達式來拋出異常。

throw MyException("Hi There!")

使用 try{: .keyword }-表達式來捕獲異常。

try {
    // 一些代碼
}
catch (e: SomeException) {
    // 處理程序
}
finally {
    // 可選的 finally 塊
}

可以有零到多個 catch{: .keyword } 塊。finally{: .keyword } 塊可以省略。
但是 catch{: .keyword } 和 finally{: .keyword } 塊至少應該存在一個。

Try 是一個表達式

try{: .keyword } 是一個表達式,即它可以有一個返回值。

val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }

try{: .keyword }-表達式的返回值是 try{: .keyword } 塊中的
最後一個表達式或者是(所有)catch{: .keyword } 塊中的最後一個表達式。
finally{: .keyword } 塊中的內容不會影響表達式的結果。

受檢的異常

Kotlin 沒有受檢的異常。這其中有很多原因,但我們會提供一個簡單的例子。

以下是 JDK 中 StringBuilder 類實現的一個示例接口

Appendable append(CharSequence csq) throws IOException;

這個簽名是什麼意思? 它是說,每次我追加一個字符串到一些東西(一個 StringBuilder、某種日誌、一個控制檯等)上時
我就必須捕獲那些 IOException。 爲什麼?因爲它可能正在執行 IO 操作(Writer 也實現了 Appendable)……
所以它導致這種代碼隨處可見的出現:

try {
    log.append(message)
}
catch (IOException e) {
    // 必須要安全
}

這並不好,參見《Effective Java》 第 65 條:不要忽略異常

Bruce Eckel 在《Java 是否需要受檢的異常?》(Does Java need Checked Exceptions?) 中指出:

通過一些小程序測試得出的結論是異常規範會同時提高開發者的生產力和代碼質量,但是大型軟件項目的經驗表明一個不同的結論——生產力降低、代碼質量很少或沒有提高。

其他相關引證:

Nothing 類型

在 Kotlin 中 throw 是表達式,所以你可以使用它(比如)作爲 Elvis 表達式的一部分:

val s = person.name ?: throw IllegalArgumentException("Name required")

throw 表達式的類型是特殊類型 Nothing
該類型沒有值,而是用於標記永遠不能達到的代碼位置。
在你自己的代碼中,你可以使用 Nothing 來標記一個永遠不會返回的函數:

fun fail(message: String): Nothing {
    throw IllegalArgumentException(message)
}

當你調用該函數時,編譯器會知道執行不會超出該調用:

val s = person.name ?: fail("Name required")
println(s)     // 在此已知「s」已初始化

Java 互操作性

與 Java 互操作性相關的信息,請參見 Java 互操作性章節中的異常部分。