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