每天学一点 Kotlin -- 对象进阶:异常处理
----《第一季Kotlin崛起:次世代Android开发 》学习笔记
总目录:每天学一点 Kotlin ---- 目录
上一篇:每天学一点 Kotlin -- 对象进阶:对象类型
下一篇:每天学一点 Kotlin -- 对象进阶:对象比较
1. 异常
1.1 跟Java中相同,程序中逻辑不对时,在运行时也会报错,举个栗子:
fun testE1() {
val s = "123"
println(s.toInt())
val s1 = "abc"
println(s1.toInt()) //java.lang.NumberFormatException: For input string: "abc"
}
fun main() {
testE1()
}
打印结果:
123
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at chapter07.TestExceptionKt.testE1(TestException.kt:9)
at chapter07.TestExceptionKt.main(TestException.kt:13)
at chapter07.TestExceptionKt.main(TestException.kt)
从打印结果可知,字符串里面不符合数字格式时,字符串转换为数字就会报错,并抛出异常:NumberFormatException。
1.2 跟Java中相同,使用try-catch(finally)语句块。举个栗子:
fun testE2(i: Int, str: String): Int {
try {
val a = 10 / i
val s = str.toInt()
return s
} catch (e: Exception) {
when (e) {
is ArithmeticException -> println("除数不能为0")
is NumberFormatException -> println("不是正确的数字格式")
else -> println("未知错误")
}
return 0
} finally {
println("函数执行完毕")
}
}
fun main() {
println("result1 = " + testE2(0,"123"))
println("result2 = " + testE2(0, "abc"))
println("result3 = " + testE2(2, "123"))
println("result4 = " + testE2(2, "abc"))
}
打印结果:
除数不能为0
函数执行完毕
result1 = 0
除数不能为0
函数执行完毕
result2 = 0
函数执行完毕
result3 = 123
不是正确的数字格式
函数执行完毕
result4 = 0
2. 自定义异常
2.1 ArithmeticException 和 NumberFormatException 这两个异常都是系统自带的,也可以自定义异常
2.2 自定义异常继承于系统的异常类。一般是继承自 Exception,举个栗子:
class MyException(msg: String) : Exception(msg) {}
fun testE3() {
var userName = "xiaoMing"
try {
if (userName != "xiaoHong") {
throw MyException("用户名错误")
}
} catch (e: Exception) {
if (e is MyException) {
println(e.message)
}
} finally {
println("用户名判断完毕")
}
}
fun main() {
testE3()
}
打印结果:
用户名错误
用户名判断完毕
2.3 上面的代码中使用 throw 关键字抛出异常,throw 后面要跟上需要抛出的异常的实例对象。
2.4 t对于 hrow 表达式,其实它的类型是 Nothing,该类型没有值,而是用于标记永远不能达到的代码位置。在代码中可以用 Nothing 标记一个永远不会返回的函数。举个栗子:
fun errorAppear(msg: String): Nothing{
throw ErrorException(msg)
}
为什么说没有返回呢?因为它到头来是抛出一个异常,而不是一个真实的值。
3. 必检异常
3.1 在 Kotlin 中,处理异常的方式与 Java 中几乎一模一样,只有一条关键不同:就是 Kotlin 中所有的异常都是非必检的。
3.2 所谓必检异常,是指必须定义成方法的一部分或者在方法内部处理。一个经典的例子就是 IOException,可以被很多文件处理相关的函数抛出,因此在很多地方最终通过 IO 库来定义它。
3.3 非必检异常是指没有什么必要加入到方法中的异常。在 Kotlin 中,因为所有异常都是非必检的,所以异常不必成为函数的组成部分。
3.4 举个栗子:
(1) 写法一:
fun readFile(path: Path): Unit{
val input = Files.newInputStream(path)
var bytes = input.read()
while(bytes != -1){
println(bytes)
bytes = input.read()
}
}
不处理异常,编译器不会报错
(2) 写法二:
fun readFile(path: Path): Unit {
val input = Files.newInputStream(path)
try {
var bytes = input.read()
while (bytes != -1) {
println(bytes)
bytes = input.read()
}
} catch (e: IOException) {
println("读取文件错误,因为: ${e.message}")
} finally {
input.close()
}
}
像 Java 中一样,使用try,catch,finally 代码块处理异常