空安全(Null Safety)
在 Kotlin 中,空安全(Null Safety) 是一項設計特性,用於避免在運行時發生 NullPointerException
(NPE)。
Kotlin 通過明確地將變量分為可空(nullable)與不可空(non-nullable)來實現空安全。
1. 不可空型別
- 預設情況下,Kotlin 的變量不能為
null
。 - 如果嘗試將
null
賦值給不可空變量,會導致編譯錯誤。
範例:
var name: String = "Kotlin"
// name = null // 編譯錯誤:`null` 無法賦值給非空型別
2. 可空型別
- 如果變量需要接受
null
值,可以在型別後加上?
來聲明為可空型別。 - 可空型別允許變數的值為
null
。
範例:
var name: String? = "Kotlin" // 可空變量初始值為 "Kotlin"
name = null // 將變量的值設為 null
println(name) // 輸出 null
3. 安全調用操作符(?.
)
- 用途:在調用可空變量的屬性或方法時,使用
?.
可以安全地執行操作。如果變量為null
,結果會直接返回null
,而不會拋出異常。
範例:
var a: String? = null // 可空變量初始值為 null
println(a?.length) // 安全調用,輸出 null,因為 a 為 null
a = "Kotlin" // 將 a 賦值為 "Kotlin"
println(a?.length) // 安全調用,輸出 6,因為 "Kotlin" 的長度為 6
4. Elvis 操作符(?:
)
- 用途:提供一個替代值,如果變量為
null
,則返回替代值。
範例:
val name: String? = null
val length = name?.length ?: 0 // 如果 name 不為 null,返回length,如果為 null,則返回 0
println(length) // 輸出 0
5. 非空斷言操作符(!!
)
- 用途:告訴編譯器變量一定不為
null
。 - 注意:如果變量實際為
null
,將拋出NullPointerException
。
範例:
val name: String? = null
// println(name!!.length) // 執行時會拋出 NullPointerException
6. 可空型別的條件檢查
在操作可空型別前,可以使用條件檢查來避免 NPE。
範例:
val name: String? = null
if (name != null) {
println(name.length) // 在這裡可以安全地使用 name
} else {
println("name is null")
}
7. let 函數與空安全
- 用途:
let
函數常與?.
結合,用於執行非空情況下的操作。
範例:
val name: String? = "Kotlin"
name?.let {
println("Name length: ${it.length}") // 如果 name 為 null,let 內部的程式碼不會執行。
}
8. 使用泛型與空安全
Kotlin 的泛型也支持空安全檢查。例如,處理列表時可以明確指定元素是否可為 null
。
範例:
val list: List<String?> = listOf("Kotlin", null, "Java")
for (item in list) {
println(item?.uppercase() ?: "Unknown") // 安全處理每個元素
}
9. 預防 NullPointerException 的關鍵
Kotlin 內建的空安全特性大大減少了 NullPointerException
,但在以下情況下可能仍會發生:
- 使用
!!
非空斷言時。 - 與 Java 程式碼交互時。
- 錯誤地初始化變量(例如,
lateinit
屬性未初始化)。