Kotlin null的处理详解
Kotlinnull的处理详解
NullPointerException,俗称NPE,不管菜鸟还是老鸟们,都是不可避免,经常遇到的一个异常,解释起来很简单,就“空指针”三个字。总是在一次不小心,而掉进这个陷阱里。Kotlin的设计目标就是希望消除代码中null引用带来的危险,也就是所谓的造成十亿美元损失的大错误.
NPE的原因
尽管Kotlin希望消除代码中的NPE,我们总是不小心,总会不小心又掉进NPE的陷阱,下面是可能NPE的原因:
- 明确调用throwNullPointerException()
- 使用!!操作符
- 外部的Java代码导致这个异常
- 初始化过程中存在某些数据不一致(在构造器中使用了未初始化的this)
避免NPE
在Kotlin中,明确区分可以指向null的引用(可为null引用)与不可以指向null的引用(非null引用).比如,一个通常的String类型变量不可以指向null:
vara:String="abc" a=null//编译错误
此时,你对a变量的任何调用都是安全的,因为它为非null,你可以对该引用做任何操作而不会报NPE。就算对a赋值给Null,编译器都会报错,不会让你通过。
可是,实际开发时,不可能所有的变量不会null,总会有情况,变量是null的,此时该如何设定该变量呢?要允许null值的变量,我们可以将变量声明为可为null的字符串,写作String?:
varb:String?="abc" b=null//ok
这样,我们是解决了变量可以设置为null的问题,可NPE的这个陷阱又设上了,如果再粗心大意,NPE又来找麻烦了。
如果我们仍然需要访问这个属性,对不对?有以下几种方法可以实现:
在条件语句中进行null检查
通过条件语句,对变量检查是否为null,对null和非null的两种情况分别处理:
if(b!=null&&b.length>0) print("Stringoflength${b.length}") else print("Emptystring")
注:
该方案只是针对当前b的值,b的值在检查以后,如果b的值被修改仍需对此值做非null检查,也就是说每次修改b的值,都必须对b作非null验证,这也导致了代码的冗余。
安全调用
什么是安全调用?看起来有点不理解,既然是null怎么还会有安全呢?
b?.length
在Kotlin中,允许使用“?.”操作符调用变量,其含义是如果b不是null,这个表达式将会返回b.length,否则返回null.如果使用了”?.”,其表达式的值也应为可为null的,比如Int?,否则编译器会报错。
bob?.department?.head?.name
安全调用在链式调用的情况下非常有用.这样的链式调用,只要属性链中任何一个属性为null,整个表达式就会返回null.
?:操作符
如果?:左侧的表达式值不是null,就会返回表达式的的值,否则,返回右侧表达式的值.
vall=b?.length?:-1
如果b不为null,将返回b的长度,如果为null,将返回-1
注:
只有在左侧表达式值为null时,才会计算右侧表达式.
由于在Kotlin中throw和return都是表达式,因此它们也可以用在Elvis操作符的右侧.这种用法可以带来很大的方便,比如,可以用来检查函数参数值是否合法。
funfoo(node:Node):String?{ valparent=node.getParent()?:returnnull valname=node.getName()?:throwIllegalArgumentException(“nameexpected”) //… }
!!操作符
对于b不为null的情况,这个表达式将会返回这个非null值(比如,在我们的例子中就是一个String类型值),如果b是null,这个表达式就
会抛出一个NPE:
vall=b!!.length()
当b为null时就抛出一个异常,你可以捕获它,而不是在不知道在某一角落里调用时,才报出异常,抓头挠腮半天,才找到NPE在哪里。
安全的类型转换
如果对象不是我们期望的目标类型,那么通常的类型转换就会导致ClassCastException,可以选择使用安全的类型转换,如果转换不成功,它将会返回null,这样避免了转换异常的抛出。
valaInt:Int?=aas?Int
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!