在 Kotlin 中, 常規变量不能容纳 null:
fun main() {
var a: String = "abc" // 默認情况下,常規初始化意味着非空
a = null // 編譯錯誤
}
如果我們希望一個變數可以容許 空值(null)的存在, 可以像下面宣告, 在類型後面 加一個問號
fun main() {
var a: String? = "abc" // 可以設置为空
a = null // ok
println(a)
// result:
// null
}
特定情況下訪問 null 的變數會導致 NullPointerException。
下面藉由了 !! 操作符 保證不為空 , 騙過了編譯器 , 但其實本質上還是 null
所以在運行時仍引發了 NullPointerException , 下面會介紹到 !! 操作符
是怎麼一回事
fun main() {
var a: String? = null // 可以設置为空
val l = a!!.toDouble()
println(l)
// error:
// Exception in thread "main" java.lang.NullPointerException
}
這時我們會需要做空安全的檢查
先檢測 值 是否為 null,並分別處理兩種可能,這樣能有效防止 NullPointerException
fun main() {
var a: String? = null // 可以設置为空
// ok
val l = if( a != null) a.toDouble() else -1
println(l)
// result
// -1
}
寫法如下
如果 a 非空,就返回 a.toDouble(),否則返回 null,这个表達式的類型是 Double?。
fun main() {
var a: String? = null // 可以設置为空
// ok
val l = a?.toDouble()
println(l)
// result
// null
}
但賦值給下一個變數時仍需做處理,否則依然會發生NullPointerException
fun main() {
var a: String? = null // 可以設置为空
// ok
val l = a?.toDouble()
val b = l!!.compareTo(9.0)
println(b)
// error:
// Exception in thread "main" java.lang.NullPointerException
}
上面提到用 if 先檢測 值 是否為 null,並分別處理兩種可能
val l = if( a != null) a.toDouble() else -1
其實我們可以簡化成下面這樣
上面提到的 Safe Calls , 原本是非空的話,就返回 a.toDouble(),否則返回 null
val l = a?.toDouble()
現在我們加上 Elvis 操作符 , 是非空的話,就執行右邊內容 a.toDouble(), 如果 為null 則執行左邊內容 返回-1
val l = a?.toDouble()?: -1
下面a 要調用 toDouble(),可是 a 雖然非空值("123")但他的型態 為 String?,在編譯階段就會報錯,提示必須傳入非空型態,這時候我們就可以調用 !! 保證他不為空 , 讓他可以過編譯器這一關 。
fun main() {
var a: String? = "123" // 可以設置为空
val l:Double= a.toDouble()// 未加!! 操作符
println(l)
// error:
// Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable
//receiver of type String?
}
改成
fun main() {
var a: String? = "123" // 可以設置为空
val l:Double= a!!.toDouble() // 加上!! 操作符
println(l)
}
他直接跳過這個 Kotlin 空安全檢查機制 保證不為空,如果是非空的值(像上面)不會報錯 ,但如果 a 是空值, 在編譯完後 仍然會 出現 NullPointerException
fun main() {
var a: String? = null // 可以設置为空
// ok
val l:Double = a!!.toDouble()
println(l)
// error:
// Exception in thread "main" java.lang.NullPointerException
}