Kotlin中?和!!的區(qū)別

很多同學(xué)剛上手使用Kotlin知道它有針對Java NullPointerException的管理榨为,而在Kotlin中?和!!均是和NullPointerException有關(guān)系葵腹,可他們的區(qū)別到底是什么呢掺冠?為什么別人開發(fā)的項目中出現(xiàn)了好多"?",而我讀起來卻滿臉問號阶女。


不懂就問百度呀确镊,確實有人解釋它們的區(qū)別嗅剖,比如:

這是輸入"kotlin ?和!!"搜索到的百度第一條答案,確實這位說的沒錯矾利。不過我覺得對于一個剛接觸KT(Kotlin)的新手來說姑裂,他恐怕需要有漢語八級才能透徹理解這兩句話的意思。

先闡述兩個概念:
"?"加在變量名后男旗,系統(tǒng)在任何情況不會報它的空指針異常舶斧。
"!!"加在變量名后,如果對象為null察皇,那么系統(tǒng)一定會報異常茴厉!

先拿Java代碼舉個例子

        ArrayList<String> myList = null;     //  創(chuàng)建一個null的隊列
        Log.d("TAG", "-->> List Size = " + myList.size());

這個例子中,執(zhí)行到Log打印隊列長度時让网,大家都知道系統(tǒng)一定會報NullPointerException呀忧。然而如果在KT中,在調(diào)用myList的時候在它后面加上一個問號myList?.size()溃睹,當(dāng)myList為null的時候直接會打印List Size = null并不會有null異常出現(xiàn)而账。

當(dāng)使用Android Studio把上面那段Java自動轉(zhuǎn)換成KT代碼寫法后:

        val myList : ArrayList<String>? = null
        Log.d("TAG", "-->> List Size = ${myList!!.size}")

編譯器為什么自動把myList.size()變成了myList!!.size呢,為什么加上的是感嘆號不是問號因篇。

這是因為編譯器在轉(zhuǎn)化時為了保證代碼轉(zhuǎn)化前后的一致性所造成的泞辐。換句話說,在Java上出異常的竞滓,轉(zhuǎn)化到KT上咐吼,編譯器任然會讓他保持拋出異常,NullPointerException也是如此商佑。

所以結(jié)合上下文可以看得出锯茄,!!加上去后好像并沒有和之前Java代碼有什么區(qū)別嘛,該null的地方任然會拋出異常茶没。所以大多數(shù)情況下都會使用?來檢測null肌幽,輪不到!!出場。!!只會在你需要對某對象進(jìn)行非空判斷抓半,并且需要拋出異常時才會使用到喂急。

那我們接下來著重講解一下?到底怎么用。
在聲明對象時笛求,把它跟在類名后面廊移,表示這個類允許為null糕簿;
在調(diào)用對象時,把它跟在對象后面狡孔,表示如果為null程序就會視而不見懂诗。
如下列代碼:

    // 這是聲明一個變量,問號跟在類名后面
    var room: Room? = Room()

    private fun checkRoom() {
        // 因為加上了問號步氏,所以可以任意的把room變成空
        room = null

        // 因為在調(diào)用時加上了問號响禽,所以程序不會拋出異常
        Log.d("TAG", "-->> room name = ${room?.roomName}")
    }

再舉個不用?的例子:

    // 這樣程序就默認(rèn)的給room加上了!!,從此以后room不允許為null
    var room: Room = Room()

    private fun checkRoom() {
        // 當(dāng)把null賦給room時荚醒,從編譯的時候就已經(jīng)不通過
        room = null
        // 并且編譯器建議把對象后面的問號刪除芋类,因為這個對象永遠(yuǎn)不為空
        Log.d("TAG", "-->> room name = ${room.roomName}")
    }

所以加上?是一種安全的寫法,它體現(xiàn)了Kotlin null safety的特性界阁。
KT的語法很靈動侯繁,定義參數(shù)還可以寫成

    val room: Room? = Room()    // 先實例化一個room,并且room可以為空
    val room: Room? = null  // 不實例化了泡躯,開始room就是空的

    val room: Room = Room()   // 實例化一個room贮竟,并且room永遠(yuǎn)不能為空
    val room = Room()   // 和上一行代碼一樣,是KT最常用的簡寫語法



然而加上問號以后程序就萬事大吉永遠(yuǎn)擺脫了NullPointerException的煩惱较剃?我們再看下一段代碼:

        val roomList: ArrayList<Room>? = null
        if (roomList?.size > 0) {
            Log.d("TAG", "-->> 房間數(shù)不是0")
        }

當(dāng)我們判斷l(xiāng)ist.size的時候咕别,編譯器會告訴我們"Operator call corresponds to a dot-qualified call 'roomList?.size.compareTo(0)' which is not allowed on a nullable receiver 'roomList?.size'."。大概意思是写穴,當(dāng)roomList為null的時惰拱,它的size返回就是"null",但是"null"不可以和int值比大小啊送,所以編譯器建議我們寫成roomList?.size!! > 0偿短。

沒錯,經(jīng)過編譯器的建議加上了!!馋没,我們程序運行到這行代碼昔逗,roomList為null時它一定會報異常。所以是不是必須得在外面套一層if(roomList != null)這種Java常見語句才能避免異常嗎篷朵?

當(dāng)然Kotlin不會讓程序出現(xiàn)這種啰嗦的代碼勾怒,所以里面提供了對象A ?: 對象B表達(dá)式,并且取消了Java中的條件表達(dá)式 ? 表達(dá)式1 : 表達(dá)式2這個三元表達(dá)式声旺。

?:表示的意思是控硼,當(dāng)對象A值為null的時候,那么它就會返回后面的對象B艾少。

        val roomList: ArrayList<Room>? = null
        val mySize= roomList?.size ?: 0  

此時mySize的值就為0,因為roomList?.size為空翼悴。

所以我們可以把上面的代碼改成這樣:

        val roomList: ArrayList<Room>? = null
        if (roomList?.size ?: 0 > 0) {    // 這一行添加了?:
            Log.d("TAG", "-->> 房間數(shù)不是0")
        }

就目前為止使缚够,用上面的??:基本上能避免程序中出現(xiàn)的所有NullPointerException幔妨。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谍椅,隨后出現(xiàn)的幾起案子误堡,更是在濱河造成了極大的恐慌,老刑警劉巖雏吭,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锁施,死亡現(xiàn)場離奇詭異,居然都是意外死亡杖们,警方通過查閱死者的電腦和手機悉抵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摘完,“玉大人姥饰,你說我怎么就攤上這事⌒⒅危” “怎么了列粪?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長谈飒。 經(jīng)常有香客問我岂座,道長,這世上最難降的妖魔是什么杭措? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任费什,我火速辦了婚禮,結(jié)果婚禮上瓤介,老公的妹妹穿的比我還像新娘吕喘。我一直安慰自己,他們只是感情好刑桑,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布氯质。 她就那樣靜靜地躺著,像睡著了一般祠斧。 火紅的嫁衣襯著肌膚如雪闻察。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天琢锋,我揣著相機與錄音辕漂,去河邊找鬼。 笑死吴超,一個胖子當(dāng)著我的面吹牛钉嘹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鲸阻,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼跋涣,長吁一口氣:“原來是場噩夢啊……” “哼缨睡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起陈辱,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤奖年,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沛贪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體陋守,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年利赋,在試婚紗的時候發(fā)現(xiàn)自己被綠了水评。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡隐砸,死狀恐怖之碗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情季希,我是刑警寧澤褪那,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站式塌,受9級特大地震影響博敬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜峰尝,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一偏窝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧武学,春花似錦祭往、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至熏矿,卻和暖如春已骇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背票编。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工褪储, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人慧域。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓鲤竹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親昔榴。 傳聞我的和親對象是個殘疾皇子辛藻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345