Kotlin-32.空指針安全/null安全(Null Safety)

官方文檔: http://kotlinlang.org/docs/reference/null-safety.html

1.可空與非空類型(Nullable types and Non-Null Types)

很多編程語言(包括Java)最常見的陷阱就是訪問null引用,
在java中會導致空指針異常NullPointerException,簡稱NPE;
因此東尼·霍爾(Tony Hoare),圖靈獎得主把Null引用稱為十億美元的錯誤!

Kotlin類型系統(tǒng)旨在消除null引用的危險,
所以在Kotlin中只有以下情況,才會導致空指針異常NullPointerException:  
    1.顯式調(diào)用 throw NullPointerException();
    2.使用 !! 操作符;
    3.外部Java代碼導致的;
    4.對于初始化,有些數(shù)據(jù)不一致(如構造函數(shù)中未初始化的this用于某個地方);

Kotlin類型系統(tǒng)能區(qū)分一個引用可null(可空引用)還是不可null(非空引用)
例如,String類型的常規(guī)變量不能為空null:
    var a: String = "abc"
    a = null //編譯錯誤,a不能為null

    //如果要允許變量為空null,需要在類型后添加問號?標記可null:
    var b: String? = "abc"
    b = null //編譯OK

    //a不能為null,所以a方法或?qū)傩?不會導致NPE(NullPointerException)
    val l = a.length

    //b可以為null,所以訪問b屬性是不安全的,kotlin編譯器會報錯
    val l = b.length //kotlin編譯器會報: 變量“b”可能為null
    //要想可以訪問b,在下文中有幾種方法: if檢查null, ?.操作符, !!操作符

2.在條件中檢查null(Checking for null in conditions)

第一個選擇,是顯式檢查b是否為null,編譯器會跟蹤所執(zhí)行檢查null:
    val l = if (b != null) b.length else -1 //編譯OK
    val l = b.length //編譯報錯

    if (b != null && b.length > 0) {
        print("String of length ${b.length}")
    } else {
        print("Empty string")
    }

提示: 在條件中檢查null,只適用于b是不可變量的情況
    (即局部變量在檢查null和使用之間沒有改變,
    或者成員變量val有幕后字段backing field且不可覆蓋overridable),
    否則可能發(fā)生在檢查之后b又變?yōu)閚ull的情況!

3.安全調(diào)用(Safe Calls)-操作符?.

第二個選擇,是使用安全調(diào)用操作符?.
如果b非空,則返回b.length,否則返回null(表達式返回類型是Int?)
    val l = b?.length //編譯OK
    val l = b.length //編譯報錯
    
安全調(diào)用?.在鏈式調(diào)用中很有用,
例如,一個員工Bob可能分配給一個部門,該部門可能有一個負責人(名字):
    //以下任意變量為null空,該鏈式調(diào)用結(jié)果就返回null
    bob?.department?.head?.name

如果只對非空值執(zhí)行操作(即忽略null),安全調(diào)用操作符?.可與let一起使用:
    val listWithNulls: List<String?> = listOf("A", null)
    for (item in listWithNulls)
        item?.let { println(it) } //輸出A,(忽略null)

4.?:操作符(Elvis Operator)

除了用完整if表達式檢查null,還可用Elvis操作符?:簡化if表達式,
如果?:左側(cè)表達式非空,就返回其左側(cè)表達式,否則返回其右側(cè)表達式
    val l = b?.length ?: -1 //當且僅當?:左側(cè)為null時,才對右側(cè)表達式求值
    //等價于
    val l: Int = if (b != null) b.length else -1

因為在Kotlin中throw,return都是表達式,所以也可在?:右側(cè),例如檢查函數(shù)參數(shù):
    fun foo(node: Node): String? {
        val parent = node.getParent() ?: return null
        val name = node.getName() ?: throw IllegalArgumentException("name expected")
        //...
    }

5.!!操作符(!! Operator)

第三個選擇,是使用操作符!!,為NPE空指針異常的愛好者準備的, 讓編譯器不檢查null
如果b變量為null,就會拋出空指針異常NullPointerException(NPE)!
例如:
    val l = b!!.length //如果b為null,會拋出空指針異常NullPointerException

6.過濾集合的可空元素-filterNotNull()

如果集合有可空類型元素的,要過濾非空元素,可用filterNotNull實現(xiàn):
    val nullableList: List<Int?> = listOf(1, 2, null, 4)
    val intList: List<Int> = nullableList.filterNotNull()

簡書:http://www.reibang.com/p/f2da6e3eb53e
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/74509791
GitHub博客:http://lioil.win/2017/07/05/Kotlin-null.html
Coding博客:http://c.lioil.win/2017/07/05/Kotlin-null.html

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晒骇,一起剝皮案震驚了整個濱河市蚕愤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汽摹,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機煎饼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來校赤,“玉大人吆玖,你說我怎么就攤上這事÷砝海” “怎么了沾乘?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浑测。 經(jīng)常有香客問我翅阵,道長,這世上最難降的妖魔是什么迁央? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任掷匠,我火速辦了婚禮,結(jié)果婚禮上漱贱,老公的妹妹穿的比我還像新娘槐雾。我一直安慰自己,他們只是感情好幅狮,可當我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布募强。 她就那樣靜靜地躺著,像睡著了一般崇摄。 火紅的嫁衣襯著肌膚如雪擎值。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天逐抑,我揣著相機與錄音鸠儿,去河邊找鬼。 笑死厕氨,一個胖子當著我的面吹牛进每,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播命斧,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼田晚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了国葬?” 一聲冷哼從身側(cè)響起贤徒,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤芹壕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后接奈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體踢涌,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年序宦,在試婚紗的時候發(fā)現(xiàn)自己被綠了睁壁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡互捌,死狀恐怖堡僻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疫剃,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布硼讽,位于F島的核電站巢价,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏固阁。R本人自食惡果不足惜壤躲,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望备燃。 院中可真熱鬧碉克,春花似錦、人聲如沸并齐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽况褪。三九已至撕贞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間测垛,已是汗流浹背捏膨。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留食侮,地道東北人号涯。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像锯七,于是被迫代替她去往敵國和親链快。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 前言 人生苦多起胰,快來 Kotlin 久又,快速學習Kotlin巫延! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,218評論 9 118
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,334評論 25 707
  • 《Kotlin 極簡教程》第一章 Kotlin簡介 科特林島(Котлин)是一座俄羅斯的島嶼地消,位于圣彼得堡以西約...
    光劍書架上的書閱讀 3,095評論 8 50
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理炉峰,服務發(fā)現(xiàn),斷路器脉执,智...
    卡卡羅2017閱讀 134,716評論 18 139
  • 獨自帶婉詞生活已有兩個年頭疼阔,一邊上班一邊帶孩子的辛苦只有經(jīng)歷過的人才真正懂得,也是這時才體味出當年母親的艱辛...
    佑妳喜樂閱讀 1,736評論 0 0