Kotlin的类型系统的目标就是在代码上消灭空引用。
kotlin只会在如下情况出现空引用:
(1)自己程序抛出;
(2)使用!!操作符;
(3)使用外部java程序;
(4)初始化数据不一致(没有初始化的数据,构造函数中没有初始化的变量被引用)。
空引用对很多开发语言而言,都是十分麻烦的事情,但Kotlin很好的解决了这个问题。解决的方法很简单,就是事先检查。
可空类型和不可空类型
定义,可空类型变量,需要在类型后面加?
var a: String = "abc"
a = null // 不可空类型不能,编译错误
var b: String? = "abc"
b = null // 可空类型,可以指定null,正确
访问:
val l1 = a.length
val l2 = b.length // error: variable 'b' can be null 错误:变量b可以是null
方案一:在条件中检查null
//简单的判断:
val l = if (b != null) b.length else -1
//更复杂的判断:
if (b != null && b.length > 0) {
print("String of length ${b.length}")
} else {
print("Empty string")
}
【注意】:b变量是不可变的才能用,不然,判断完了,b同时被赋值为null,你再读取,还是会出空引用。
方案二:安全调用
操作符:
?.
b?.length()
方案三:Elvis操作符
操作符:
?:
val l = b?.length ?: -1
语句的意思是上文的if else一样,如果不空,返回长度,如果空,返回-1;
【注意】,throw和retun在Kotlin中是表达式,能够使用在Elvis操作符右边,例如检测函数参数:
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
// ...
}
方案四:!!操作符
val l = b!!.length
如果b不是null,返回数值,如果是,返回一个空引用异常。
方案五:安全的类型转换
如果对象不是目标类型,通常的转换会导致类转换异常,我们可以使用安全的类型转换:
val aInt: Int? = a as? Int
可空类型的容器
如果你有一个允许空的容器,查询不可空数据的代码:
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()