Kotlin空指針安全(null-safety)筆記

Kotlin語言基礎(chǔ)筆記

Kotlin流程控制語句筆記

Kotlin操作符重載與中綴表示法筆記

Kotlin擴(kuò)展函數(shù)和擴(kuò)展屬性筆記

Kotlin空指針安全(null-safety)筆記

Kotlin類型系統(tǒng)筆記

Kotlin面向?qū)ο缶幊坦P記

Kotlin委托(Delegation)筆記

Kotlin泛型型筆記

Kotlin函數(shù)式編程筆記

Kotlin與Java互操作筆記

Kotlin協(xié)程筆記

多年的java開發(fā)經(jīng)驗(yàn)總結(jié)得出,至少50%以上的線上bug都是NPE(NullPointException)引起的。在java代碼中充斥著大量的非空判斷,如果是有多層的對(duì)象,比如person.getAddress().getCity(),你需要判斷person非空,然后判斷address非空,只有兩個(gè)都非空時(shí),才能安全的獲取到city。這樣的代碼非常冗余和惡心。

現(xiàn)在我們來看看Kotlin做了那些事情讓我們來避免NPE錯(cuò)誤。

1. 可為null類型

在Kotlin中通常我們直接定義的類型是不可為null的,如下:

data class Person(val name:String)

fun main(args: Array<String>) {
    var s = "abc"
    s = null  //編譯錯(cuò)誤:null can not be a value of a non-null type String

    var i = 1
    i = null  //編譯錯(cuò)誤:null can not be a value of a non-null type Int

    var p = Person("Denny")
    p = null  //編譯錯(cuò)誤:null can not be a value of a non-null type Person
}

如果要允許為null,我們需要在變量的類型后面加個(gè)?號(hào)。如下:

data class Person(val name:String)

fun main(args: Array<String>) {
    var s: String? = "abc"
    s = null

    var i:Int? = 1
    i = null

    var p:Person? = Person("Denny")
    p = null

    var list:MutableList<Int>? = mutableListOf(1, 2, 3)
    list = null
}

2. 安全調(diào)用

上面的例子中,如果調(diào)用s.length的話,這將是不安全的,編譯器直接報(bào)錯(cuò)。

npe

編譯器已經(jīng)告訴你了要使用安全調(diào)用(?.)或者非空斷言調(diào)用(!!.)才被允許在String?類型上。

fun main(args: Array<String>) {
    var s: String? = "abc"
    s = null
    println(s?.length)  //打印null
    println(s!!.length)  //拋出Exception in thread "main" kotlin.KotlinNullPointerException異常
}

另外我們?cè)倏纯聪旅孢@段有趣的代碼:

fun main(args: Array<String>) {
    var s: String? = "abc"
    println(s is Any)    //打印true
    println(s is Any?)   //打印true
    s = null
    println(s is Any)   //打印false
    println(s is Any?)  //打印true
}

安全調(diào)用在鏈?zhǔn)秸{(diào)用上非常有用,比如上面java代碼person.getAddress().getCity(),在Kotlin中使用安全調(diào)用的話就是person?.getAddress()?.getCity()。只要person或者address有一個(gè)為null的話,整個(gè)表達(dá)式就返回null。比java中用2個(gè)if來判斷非空好多了。
如果對(duì)某個(gè)非空值執(zhí)行某個(gè)操作,安全調(diào)用操作符可以和let一起使用。比如:

fun main(args: Array<String>) {
    val list = listOf("a", "b", null)
    println(list) 

    list.forEach { it?.let { println(it) } }
}

輸出

[a, b, null]
a
b

最后你還可以使用Elvis錯(cuò)作符,之前的文章有說過。

fun main(args: Array<String>) {
    var name:String? = null
    name = name?:"Unknown"
    println(name)   //打印Unknown
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容