08. 空值和异常
08. 空值和异常
0. null是什么
null是空值的意思,他在kotlin中是一种异常。
就像一个空杯子,喝的时候必须有水,没水就是异常。 钱包里必须有钱,花钱的时候没钱就是异常。
当然,我的杯子,我可以在一开始的时候声明他没水(可空类型)
但是我喝的时候,杯子可能没水这件事,kotlin会显式的提醒我们,兄弟这可能没水(告诉你必须安全的调用它),你得瞅瞅或是掂量下(做出检查 if判空 ?.操作符)
1. 空变量的声明
kotlin中,对变量的声明往往需要初始化属性
局部变量无需初始化,但是一旦被使用,仍然会被编译器提示必须初始化属性。
1.1 局部变量
1.1.1 不使用a变量的情况
fun test(){
val a:Int
}
1.1.2 使用未初始化的a变量时
编译器依然提示异常
fun test(){
val a:Int
nullTest(a)
}
fun nullTest(a:Int){
}
1.2 (成员变量/实例变量) ,(类变量/静态变量)
他们在编写时,都会被编辑器检查未出初始化属性的异常。 换句话说, 他们都必须初始化属性
1.3 例外的情况
1.3.1 抽象属性
抽象属性,接口中的属性(隐式转换为抽象属性)。 由于他们都是无法被实例化的类,所以他们可以声明为空,因为他们也必须被实现,并且不能为空。
1.3.2 lateinit的非基本类型变量
注意:基本类型不允许lateinit
lateinit的意思是在使用时初始化属性。如果在使用时未初始化,就会抛出异常。
data class People(var name: String, var age: Int){
constructor(age: Int) :this("赵思琦",age)
}
fun main(args: Array<String>) {
lateinit var people: People
people
}
例子:
lateinit var she: DreameLove
斯人如彩虹,遇上放知有
总结
kotlin在任何时候都不允许变量为空,因为kotlin认为,null是一种异常状态,所以他不允许这样的情况出现。
2. 显式的声明类型可空
val people: People? = null
3. 避免空值(null)造成的异常问题
3.1 ?.操作符
保证可空类型的安全,无非两种方式。 判空或是抛出异常。
val people: People? = null
people?.name = "赵思琦"
val myName = people?.name
等价于
val people: People? = null
if(people!=null){
people.name="赵思琦"
}
if(people!=null){
val myName = people?.name
}
仅此而已。
3.2 Elvis操作符
这样的叫法只是因为?:像猫王
他很像三目运算符,但是比三木运算符少了:前的返回值,并且也只是判断该值是否为空,为空 返回:后的值。
val people=People(null)
val myAge=people.age?:2
println(myAge)
等价于
data class People(var name: String, var age: Int?) {
constructor(age: Int?) : this("赵思琦", age)
}
fun main(args: Array<String>) {
val people=People(null)
var myAge:Int
if(people.age==null){
myAge=2
}else{
myAge=people.age!!
}
}
3.3 !! 非空断言
断言该值不可能为空,如果为空那么编译器就会抛出异常。
3.2 作用域函数let
用处:执行非空代码块,提升可读性。
3.2.1 执行非空代码块
上下文对象作为lambda表达式参数来访问,返回值是lambda表达式的结果
var people:People?=null
people?.let {
println("执行一些非空情况的代码")
}
输出
... 什么也不输出
当然,他不为空时,就会执行代码块中的代码。
3.2.2 返回表达式结果
var people:People?=People(27)
val myName=people?.let {
it.name
}
println(myName)
3.2.3 总结
let适用于执行非空代码块并需要返回表达式结果时使用。
4. 异常
4.1 捕获异常
try {
val people:People=People(null)
val age= people.age!!
}catch (e:NullPointerException){
println(e.message)
}
4.2 抛出异常
try {
throw NullPointerException("这是一个我随便抛出的空异常")
}catch (e:Exception){
println(e.message)
}finally {
println("每次都有我")
}
4.3 表达式方式
4.3.1 try表达式
val age=try {
throw NullPointerException("这是一个我随便抛出的空异常")
1
}catch (e:Exception){
2
}finally {
println("每次都有我")
3
}
println(age)
输出
2
这说明表达式只会返回try catch中的返回值
4.3.2 throw表达式
val age:Int?=null
val myAge=age?:throw NullPointerException("这是一个空的年龄")
于Elvis操作符结合使用。