如需轉(zhuǎn)載請(qǐng)?jiān)u論或簡(jiǎn)信斋枢,并注明出處,未經(jīng)允許不得轉(zhuǎn)載
Kotlin系列導(dǎo)讀
Kotlin學(xué)習(xí)手冊(cè)(一)類(lèi)與繼承
Kotlin學(xué)習(xí)手冊(cè)(二)屬性與字段
Kotlin學(xué)習(xí)手冊(cè)(三)接口
Kotlin學(xué)習(xí)手冊(cè)(四)內(nèi)部類(lèi)
Kotlin學(xué)習(xí)手冊(cè)(五)函數(shù)
Kotlin學(xué)習(xí)手冊(cè)(六)數(shù)組與集合
Kotlin學(xué)習(xí)手冊(cè)(七)for循環(huán)
Kotlin學(xué)習(xí)手冊(cè)(八)內(nèi)聯(lián)函數(shù)let蟹演、with酒请、run囤萤、apply富雅、also
Kotlin學(xué)習(xí)手冊(cè)(九)空類(lèi)型安全
Kotlin學(xué)習(xí)手冊(cè)(十)帶你真正理解什么是Kotlin協(xié)程
目錄
前言
Kotlin 的類(lèi)型系統(tǒng)旨在消除來(lái)自代碼空引用的危險(xiǎn),也稱為《十億美元的錯(cuò)誤》
在Kotlin中痹屹,“空”也是一種類(lèi)型,將空指針問(wèn)題在編譯期間就拋出來(lái)嘲恍,而不是等到運(yùn)行時(shí)才發(fā)現(xiàn)淹辞。如String
和String?
是可以看做是兩種不同的類(lèi)型爷速,下面我們會(huì)詳細(xì)進(jìn)行介紹
空類(lèi)型
- 非空類(lèi)型
聲明了非空類(lèi)型(如String
)的變量莉给,不能容納 null
var a: String = "abc"
a = null // 編譯錯(cuò)誤
var a: String = null // 編譯錯(cuò)誤
- 空類(lèi)型
如果一個(gè)變量想要容納空類(lèi)型颓遏,那么就需要用空類(lèi)型進(jìn)行聲明(如String?
)
var b: String? = "abc"
b = null // ok
空安全調(diào)用
- 非空類(lèi)型
像在java中一樣進(jìn)行安全調(diào)用
val a = "Kotlin"
println(a.length) // 無(wú)需安全調(diào)用
- 空類(lèi)型
需要通過(guò)?.
進(jìn)行調(diào)用滤灯,不然無(wú)法通過(guò)編譯鳞骤,b?.length
表示如果b為空,那么這段語(yǔ)句將不會(huì)執(zhí)行
val b: String? = null
println(b?.length)
kotlin還支持鏈?zhǔn)秸{(diào)用黍判,只要鏈上有一個(gè)值為空弟孟,那么將不會(huì)往下執(zhí)行。鏈?zhǔn)秸{(diào)用其實(shí)就是對(duì)java中的層層判空的一種代碼結(jié)構(gòu)優(yōu)化
bob?.department?.head?.name
Elvis操作符
有一段if-else
表達(dá)式
val l: Int = if (b != null) b.length else -1
通過(guò)Elvis操作符可以將上面的代碼進(jìn)行簡(jiǎn)化样悟,寫(xiě)作?:
如果 ?:
左側(cè)表達(dá)式非空,返回左側(cè)表達(dá)式庭猩,否則返回右側(cè)表達(dá)式
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")
// ……
}
非空斷言
當(dāng)你認(rèn)為你所使用的對(duì)象肯定不為空的時(shí)候窟她,你可以使用!!
來(lái)進(jìn)行非空斷言,這也能繞過(guò)編譯器的空類(lèi)型檢查蔼水。除非你完全清楚你為什么要使用它震糖,不然非常不推薦使用非空斷言。因?yàn)槿绻娴某霈F(xiàn)了null
的情況趴腋,那就會(huì)造成一個(gè)Null Point Exception
val a = b!!.length
安全轉(zhuǎn)換
普通的轉(zhuǎn)換可能產(chǎn)生 ClassCastException
異常吊说。使用as?
操作符嘗試轉(zhuǎn)換成指定類(lèi)型,如果轉(zhuǎn)換不成功則返回 null
fun main() {
var a = "abc"
var b: Int ? = a as? Int
println(b) // 輸出 null
}
過(guò)濾可空集合
使用filterNotNull
操作符优炬,過(guò)濾一個(gè)可空類(lèi)型元素集合中的非空元素
fun main() {
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()
println(intList) // 輸出 [1, 2, 4]
}