詳解Kotlin的空指針處理
詳解Kotlin的空指針處理
Kotlin的空指針處理相比于java有著極大的提高,可以說是不用擔(dān)心出現(xiàn)NullPointerException的錯誤,kotlin對于對象為null的情況有嚴(yán)格的界定,編碼的階段就需要用代碼表明引用是否可以為null,為null的情況需要強(qiáng)制性的判斷處理。
咋看一下這些在java里面其實(shí)也有,問題是一般開發(fā)中不寫也是可以的(大部分開發(fā)不會花很多時間考慮這些),等出了空指針錯誤再一個個打補(bǔ)丁。這樣往往會遺漏很多空指針,后期的解決僅僅是做一個if判斷,沒有從根源解決問題
變量需要知道是否可以為null
第一個與java的不同,kotlin聲明引用時不可以直接賦值為null
var helloA: String=null //編譯器直接報錯 null can not be value of a non null type string
這里插一句,kotlin的成員變量(全局變量)必須要初始化甚至是基本數(shù)據(jù)類型都要手動給一個初始值,局部變量可以不用初始化,上面的例子是成員變量的聲明。
編譯器直接表示hello是一個non null type你不可以直接賦一個null值。對于我們java原住民來說聲明變量時如果不去賦值,編譯器會默認(rèn)賦null(除去基本數(shù)據(jù)類型),在kotlin這是不允許的。
類型?
當(dāng)某個變量的值可以為 null 的時候,必須在聲明處的類型后添加 ? 來標(biāo)識該引用可為空。
這是官方文檔的說明,也就是說上面的變量聲明只需要在String類型后面加一個?就可以解決這個錯誤。
var helloB : String? = null
如果不用?也可以直接初始化來解決問題
var helloA : String = "hello"
String和String?
helloA 和 helloB2個變量的類型分別為String和String?,這2種類型的區(qū)別在于引用時是否空安全,String?代表可能為空,引用不安全,String代表不會為空,引用安全。比如調(diào)用一下helloB的方法

可以看到有些方法是灰的代表不能直接調(diào)用,有些是白的代表可以直接調(diào)用,為什么可以直接調(diào)用后面再講
helloB.length //Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
這里的錯誤解釋簡單的理解就是helloB是一個可能為空的類型(String?),對于可空類型你必須做判空的處理才能調(diào)用方法。有沒有愛上kotlin? wtf太厲害了
如何做判空處理
最簡單的方法就是使用?.來調(diào)用方法。這個符號的意義是,當(dāng)helloB不為空調(diào)用.length方法,返回Int值,如果helloB為空則返回null。
helloB?.length
注意這里的返回值類型為Int? 依然是可以為空的類型
不推薦的寫法!!這個操作符可以說是為了空指針錯誤愛好者準(zhǔn)備的,使用了!!操作符代表你不關(guān)心變量的空判斷可以報出NullPointerException,又或者你有絕對的自信這里肯定不為空,可以放心的調(diào)用,可以說!!放棄了判空的檢查
helloB!!.length
Elvis 操作符?:
回到?.的調(diào)用上來,這個調(diào)用方式存在一個讓人不安的處理,就是在變量為null的情況下,會直接返回null,這樣空指針的隱患還在。
var l : Int = helloB?.length //報錯類型不匹配 Int? 和 Int
修正的話需要通過if判斷來進(jìn)行判空處理
var l: Int = if (helloB?.length != null) helloB.length else -1
這種寫法可以簡化成Elvis 操作符?:
var le: Int = helloB?.length ?: 0
當(dāng)?:左邊非空返回左邊的值,左邊為空則返回右邊的值
最后前文提到的當(dāng)helloB為空時有些方法仍然可以調(diào)用比如equals方法
helloB.equals(helloA)
即使helloB為可空類型依然可以調(diào)用equals方法,但是這里的equals方法并不是String.java的equals方法,而是StringJvm.kt中的equals方法
public fun String?.equals(other: String?, ignoreCase: Boolean = false): Boolean {
if (this === null)
return other === null
return if (!ignoreCase)
(this as java.lang.String).equals(other)
else
(this as java.lang.String).equalsIgnoreCase(other)
}
關(guān)鍵代碼
this===null return other === null
這個方法對變量本身為null的情況已經(jīng)做了判斷,同時方法寫成了String?.equals可以讓String?類型的對象直接調(diào)用這個equals方法
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
RocketMQ?offset確認(rèn)機(jī)制示例詳解
這篇文章主要為大家介紹了RocketMQ?offset確認(rèn)機(jī)制示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
詳解Java程序并發(fā)的Wait-Notify機(jī)制
這篇文章主要介紹了詳解Java程序并發(fā)的Wait-Notify機(jī)制,多線程并發(fā)是Java編程中的重要部分,需要的朋友可以參考下2015-07-07
Java實(shí)現(xiàn)復(fù)制文件并命名的超簡潔寫法
這篇文章主要介紹了Java實(shí)現(xiàn)復(fù)制文件并命名的超簡潔寫法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
java高并發(fā)下CopyOnWriteArrayList替代ArrayList
這篇文章主要為大家介紹了java高并發(fā)下CopyOnWriteArrayList替代ArrayList的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
通過實(shí)例解析Java分布式鎖三種實(shí)現(xiàn)方法
這篇文章主要介紹了通過實(shí)例解析Java分布式鎖三種實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
Java實(shí)現(xiàn)字符編碼轉(zhuǎn)換(utf-8/gbk)
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)字符編碼轉(zhuǎn)換工具,主要針對UTF-8和GBK兩種編碼格式,文中的示例代碼講解詳,需要的可以了解下2025-03-03
詳解使用Spring Security進(jìn)行自動登錄驗(yàn)證
本篇文章主要介紹了詳解使用Spring Security進(jìn)行自動登錄驗(yàn)證,非常具有實(shí)用價值,需要的朋友可以參考下2017-09-09

