如需转载请评论或简信,并注明出处,未经允许不得转载
Kotlin系列导读
Kotlin学习手册(一)类与继承
Kotlin学习手册(二)属性与字段
Kotlin学习手册(三)接口
Kotlin学习手册(四)内部类
Kotlin学习手册(五)函数
Kotlin学习手册(六)数组与集合
Kotlin学习手册(七)for循环
Kotlin学习手册(八)内联函数let、with、run、apply、also
Kotlin学习手册(九)空类型安全
Kotlin学习手册(十)带你真正理解什么是Kotlin协程
目录
前言
Kotlin 的类型系统旨在消除来自代码空引用的危险,也称为《十亿美元的错误》
在Kotlin中,“空”也是一种类型,将空指针问题在编译期间就抛出来,而不是等到运行时才发现。如String
和String?
是可以看做是两种不同的类型,下面我们会详细进行介绍
空类型
- 非空类型
声明了非空类型(如String
)的变量,不能容纳 null
var a: String = "abc"
a = null // 编译错误
var a: String = null // 编译错误
- 空类型
如果一个变量想要容纳空类型,那么就需要用空类型进行声明(如String?
)
var b: String? = "abc"
b = null // ok
空安全调用
- 非空类型
像在java中一样进行安全调用
val a = "Kotlin"
println(a.length) // 无需安全调用
- 空类型
需要通过?.
进行调用,不然无法通过编译,b?.length
表示如果b为空,那么这段语句将不会执行
val b: String? = null
println(b?.length)
kotlin还支持链式调用,只要链上有一个值为空,那么将不会往下执行。链式调用其实就是对java中的层层判空的一种代码结构优化
bob?.department?.head?.name
Elvis操作符
有一段if-else
表达式
val l: Int = if (b != null) b.length else -1
通过Elvis操作符可以将上面的代码进行简化,写作?:
如果 ?:
左侧表达式非空,返回左侧表达式,否则返回右侧表达式
val l = b?.length ?: -1
还可以搭配return
和throw
使用
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
// ……
}
非空断言
当你认为你所使用的对象肯定不为空的时候,你可以使用!!
来进行非空断言,这也能绕过编译器的空类型检查。除非你完全清楚你为什么要使用它,不然非常不推荐使用非空断言。因为如果它真的出现了null
的情况,那就会造成一个Null Point Exception
val a = b!!.length
安全转换
普通的转换可能产生 ClassCastException
异常。使用as?
操作符尝试转换成指定类型,如果转换不成功则返回 null
fun main() {
var a = "abc"
var b: Int ? = a as? Int
println(b) // 输出 null
}
过滤可空集合
使用filterNotNull
操作符,过滤一个可空类型元素集合中的非空元素
fun main() {
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()
println(intList) // 输出 [1, 2, 4]
}