什么是异常?
异常可以导致程序停止运行,而正确处理异常可以帮助我们避免这种情况并使程序可以正确运行。
Java异常
java异常可分为已检异常和未检异常。它们最大的区别在于已检异常是由编译器强制执行的,用于指示不受程序控制的异常情况(例如,I/O 错误),而未检异常发生在程序运行时并用于指示编程错误(例如,空指针)。
kotlin异常
所有的kotlin异常都由 Throwable
类派生,要抛出一个异常时我们可以使用 throw
关键字。
比较特别的是在kotlin中没有已检异常,这意味着在编写程序时,编译器不会提示程序控制的异常情况,这是怎么回事呢?可以看看官网异常文档中对此的解释,这里直接给结论:
通过一些小程序测试得出的结论是异常规范会同时提高开发者的生产力与代码质量,但是大型软件项目的经验表明一个不同的结论——生产力降低、代码质量很少或没有提高。
处理异常的流程
没错,就是try-catch-finally!
try后面必须跟上至少一个catch或者finally块,不过一般来说我们只使用try-catch,如果需要释放try-catch块中使用的资源或处理其他情况才加上finally块。
一个try可以有多个catch块,并且只运行第一个匹配的catch块。因此建议写多个catch块,并从特定异常到通用异常。
fun main(args: Array<String>) {
try {
var a = 0
var x = 7 / a
val v = "Journaldev.com"
v.toInt()
} catch (e: ArithmeticException) {
println("Arthimetic Exception")
} catch (e: Exception) {
println("Exception occured. To print stacktrace use e")
} finally {
println("Finally. It's over")
}
}
try是表达式
try-catch可以作为表达式使用,来获取语句块中执行的值,就像我们kotlin中常用的if-else表达式。
fun main(args: Array<String>) {
var x= "Androidly.net"
var a = try { x.toInt() } catch (e: NumberFormatException) { "This is a string" }
println(a)
x = "5"
a = try { x.toInt() } catch (e: NumberFormatException) { "This is a string" }
println(a)
}
需要注意的是finally语句不会被当成表达式。
快速抛出异常
import kotlin.test.fail
class User {
var name: String? = ""
}
fun main(args: Array<String>) {
var user = User()
user.name = null
val n: String = user.name ?: fail("No name found")
print(5)
}
上面的代码中如果user.name
是null的话会执行fail
函数,该函数执行后程序在打印"No name found"
后将停止运行。这是因为fail
函数会抛出异常:
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}
Nothing
是throw
返回的特殊类型。
将内联函数与异常处理一同使用
内联函数可以让try-catch块变得十分简洁,而且也不会因此产生额外开销。
fun main(args: Array<String>) {
simpleTryCatch {
var x = 0
var y = 7
var z = y / x
}
simpleTryCatch {
var x = "Androidly"
var number = x.toInt()
}
}
inline fun simpleTryCatch(action: () -> Unit) {
try {
action()
} catch (t: Throwable) {
println("Caught something. ${t.message}")
}
}
参考: