一、可空類型系統
Kotlin默認所有的參數和變量都不可爲空。
Int 表示不可爲空的整型
Int? 表示可爲空的整型
eg:
fun doStudy(study: Study?) {
if (study != null) {
study.doHomeWork()
study.readBook()
}
}
有點囉嗦吧,別急,Kotlin還提供了一系列輔助工具幫我們作判空處理。
二、判空輔助工具
1. ?.操作符
表示當對象不爲空的時候正常調用相應的方法,當對象爲空的時候什麼都不做。
使用 ?.操作符改變上面代碼:
fun doStudy(study: Study?) {
study?.doHomeWork()
study?.readBook()
}
2. ?:操作符
這個操作符左右兩邊都接收一個表達式,如果左邊的表達式的結果不爲空就返回左邊表達式的結果,否則就返回右邊表達式的結果。
//原代碼
var c = if (a != nul) a else b
//使用?:操作符
var c = a ?: b
3. !!操作符
Kotlin也不是特別的智能,有時候我們邏輯上已經將空指針異常處理了,單Kotlin編譯器並不知道,那麼這個時候還是會編譯失敗,比如以下例子:
var content: String? = "hello"
fun main() {
if (content != null) {
printUpperCase()
}
}
fun printUpperCase() {
val toUpperCase = content.toUpperCase()
print(toUpperCase)
}
這段代碼邏輯沒問題,但是一定無法執行。因爲printUpperCase()函數並不知道外部已經對content做了非空檢查,所以在調用toUpperCase()時,還認爲存在空指針方風險。
使用!!操作符:
fun printUpperCase() {
val toUpperCase = content!!.toUpperCase()
print(toUpperCase)
}
這是一個種有風險的寫法,意在告訴Kotlin,我非常確信這裏的對象不會是空,所以不用你來做非空檢查了,如果出現問題,可以直接拋出空指針異常,後果我自己承擔。
4. let函數
let既不是操作符也不是關鍵字,是一種函數。這個函數提供了函數式API的編程接口,並將原始調用對象作爲參數傳遞到lambda表達式中,示例代碼:
obj.let { obj2 ->
//編寫具體的業務邏輯
}
obj與obj2是一個對象。
let函數配合?.操作符做空檢查:
fun doStudy(study: Study?) {
study?.let { stu ->
stu.readBook()
stu.doHomeWork()
}
}
這樣我們對study對象只做了一次非空判斷就可以使用了。
優化之後:
fun doStudy(study: Study?) {
study?.let {
it.readBook()
it.doHomeWork()
}
}
另外,let函數是可以處理全局變量的判空問題的。而if無法做到這一點。