空安全
可空類型和非空類型
在 Kotlin 類型系統(tǒng)中可以為空和不可為空的引用是不同的。比如违诗,普通的 String 類型的變量不能為空:
var a: String ="abc"
a = null //編譯錯誤
允許為空,我們必須把它聲明為可空的變量:
var b: String? = "abc"
b = null
現(xiàn)在你可以調(diào)用 a 的方法作箍,而不用擔(dān)心 NPE 異常了:
val l = a.length()
但如果你想使用 b 調(diào)用同樣的方法就有可能報錯了:
val l = b.length() //錯誤:b 不可為空
在條件中檢查 null
首先片橡,你可以檢查 b 是否為空,并且分開處理下面選項:
val l = if (b != null)
b.length()
else
-1
編譯器會跟蹤你檢查的信息并允許在 if 中調(diào)用 length()跃脊。更復(fù)雜的條件也是可以的:
if (b != null && b.length() >0)
print("Stirng of length ${b.length}")
else
print("Empty string")
注意只有在 b 是不可變時才可以
安全調(diào)用
第二個選擇就是使用安全操作符宇挫,?.:
b?.length()
如果 b 不為空則返回長度,否則返回空酪术。這個表達式的的類型是 Int?
安全調(diào)用在鏈?zhǔn)秸{(diào)用是是很有用的器瘪。比如,如果 Bob 是一個雇員可能分配部門(也可能不分配)绘雁,如果我們想獲取 Bob 的部門名作為名字的前綴橡疼,就可以這樣做:
bob?.department?.head?.name
這樣的調(diào)用鏈在任何一個屬性為空都會返回空。
Elvis 操作符
當(dāng)我們有一個 r 的可空引用時庐舟,我們可以說如果 r 不空則使用它欣除,否則使用使用非空的 x :
val l: Int = if (b != null) b.length() else -1
盡管使用 if 表達式我們也可以使用 Elvis 操作符,?:
val l = b.length()?: -1
如果 ?: 左邊表達式不為空則返回挪略,否則返回右邊的表達式历帚。注意右邊的表帶式只有在左邊表達式為空是才會執(zhí)行
注意在 Kotlin 中 throw return 是表達式,所以它們也可以在 Elvis 操作符右邊杠娱。這是非常有用的挽牢,比如檢查函數(shù)參數(shù)是否為空;
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
//...
}
!! 操作符
第三個選擇是 NPE-lovers摊求。我們可以用 b!! 禽拔,這會返回一個非空的 b 或者拋出一個 b 為空的 NPE
val l = b !!.length()
安全轉(zhuǎn)換
普通的轉(zhuǎn)換可能產(chǎn)生 ClassCastException 異常。另一個選擇就是使用安全轉(zhuǎn)換睹簇,如果不成功就返回空:
val aInt: Int? = a as? Int