Kotlin Reference: Exceptions
Contents
Exception Classes
在 Kotlin 中,所有的异常类都是 Throwable
的子类。每一个异常都有一个消息、调用栈和一个可选的原因。
使用 throw
表达式抛出异常对象:
[code lang=”kotlin”]throw MyException(“Hi There!”)[/code]
使用 try
表达式捕获异常:
[code lang=”kotlin”]try {
// some code
}
catch (e: SomeException) {
// handler
}
finally {
// optional finally block
}[/code]
可以有零个或多个 catch
代码块,finally
块可以省略,但必须至少有一个 catch
或 finally
。
Try is an expression
try
是一个表达式,也就是说,它可以有返回值。
[code lang=”kotlin”]val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }[/code]
try
表达式的返回值是 try
块中的最后一个表达式,或者是 catch
块中的最后一个表达式。finally
块中的内容不会影响表达式的结果。
Checked Exceptions
Kotlin 中没有受检异常(Checked Exception),这样做有很多原因,我们会提供一个简单的例子。
下面是 JDK 中的一个接口,由 StringBuilder
类实现:
[code lang=”java”]Appendable append(CharSequence csq) throws IOException;[/code]
该接口的签名表示,每当追加一个字符串到某处(如 StringBuilder
,某种日志,控制台等),就必须捕获 IOExceptions
,因为可能在进行 IO 操作(Writer
也实现了 Appendable
)······因此,下面的代码随处可见:
[code lang=”java”]try {
log.append(message)
}
catch (IOException e) {
// Must be safe
}[/code]
正如 Effective Java “条目 64:不要忽视异常” 所述,这样并不好。
Bruce Eckel 在 Does Java need Checked Exceptions? 中说:
通过对小型程序的审查可以得出这样的结论:规范的异常可以提高开发者的效率,并提高代码质量。但凭借大型软件项目的开发经验则会得出不同的结论:这样做会降低效率,对代码质量的提升也微乎其微。
其他的例证还有:
- Java’s checked exceptions were a mistake (Rod Waldhoff)
- The Trouble with Checked Exceptions (Anders Hejlsberg)
The Nothing type
throw
在 Kotlin 中也是一个表达式,可以把它作为 Elvis 表达式的一部分:
[code lang=”java”]val s = person.name ?: throw IllegalArgumentException(“Name required”)[/code]
throw
表达式的类型是一个特殊的类型 Nothing
,这个类型没有值,用于标记不可能执行到的代码位置。在代码中,可以使用 Nothing
标记从不返回的函数:
[code lang=”java”]fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}[/code]
当你调用这个函数时,编译器知道程序不会继续往下执行。
[code lang=”java”]val s = person.name ?: fail(“Name required”)
println(s) // s is known to be initialized at this point[/code]
【注】上面的代码中,println(s)
时可以确定 s
已经被初始化,因为如果 person.name
为 null
,fail("Name required")
会抛出异常,程序不会再往下执行。
Java Interoperability
对于与 Java 的互操作性的信息,请参考 Java Interoperability 中关于异常的一节。