官方文檔: http://kotlinlang.org/docs/reference/null-safety.html
1.可空與非空類型(Nullable types and Non-Null Types)
很多編程語言(包括Java)最常見的陷阱就是訪問null引用,
在java中會導致空指針異常NullPointerException,簡稱NPE;
因此東尼·霍爾(Tony Hoare),圖靈獎得主把Null引用稱為十億美元的錯誤!
Kotlin類型系統(tǒng)旨在消除null引用的危險,
所以在Kotlin中只有以下情況,才會導致空指針異常NullPointerException:
1.顯式調(diào)用 throw NullPointerException();
2.使用 !! 操作符;
3.外部Java代碼導致的;
4.對于初始化,有些數(shù)據(jù)不一致(如構造函數(shù)中未初始化的this用于某個地方);
Kotlin類型系統(tǒng)能區(qū)分一個引用可null(可空引用)還是不可null(非空引用)
例如,String類型的常規(guī)變量不能為空null:
var a: String = "abc"
a = null //編譯錯誤,a不能為null
//如果要允許變量為空null,需要在類型后添加問號?標記可null:
var b: String? = "abc"
b = null //編譯OK
//a不能為null,所以a方法或?qū)傩?不會導致NPE(NullPointerException)
val l = a.length
//b可以為null,所以訪問b屬性是不安全的,kotlin編譯器會報錯
val l = b.length //kotlin編譯器會報: 變量“b”可能為null
//要想可以訪問b,在下文中有幾種方法: if檢查null, ?.操作符, !!操作符
2.在條件中檢查null(Checking for null in conditions)
第一個選擇,是顯式檢查b是否為null,編譯器會跟蹤所執(zhí)行檢查null:
val l = if (b != null) b.length else -1 //編譯OK
val l = b.length //編譯報錯
if (b != null && b.length > 0) {
print("String of length ${b.length}")
} else {
print("Empty string")
}
提示: 在條件中檢查null,只適用于b是不可變量的情況
(即局部變量在檢查null和使用之間沒有改變,
或者成員變量val有幕后字段backing field且不可覆蓋overridable),
否則可能發(fā)生在檢查之后b又變?yōu)閚ull的情況!
3.安全調(diào)用(Safe Calls)-操作符?.
第二個選擇,是使用安全調(diào)用操作符?.
如果b非空,則返回b.length,否則返回null(表達式返回類型是Int?)
val l = b?.length //編譯OK
val l = b.length //編譯報錯
安全調(diào)用?.在鏈式調(diào)用中很有用,
例如,一個員工Bob可能分配給一個部門,該部門可能有一個負責人(名字):
//以下任意變量為null空,該鏈式調(diào)用結(jié)果就返回null
bob?.department?.head?.name
如果只對非空值執(zhí)行操作(即忽略null),安全調(diào)用操作符?.可與let一起使用:
val listWithNulls: List<String?> = listOf("A", null)
for (item in listWithNulls)
item?.let { println(it) } //輸出A,(忽略null)
4.?:操作符(Elvis Operator)
除了用完整if表達式檢查null,還可用Elvis操作符?:簡化if表達式,
如果?:左側(cè)表達式非空,就返回其左側(cè)表達式,否則返回其右側(cè)表達式
val l = b?.length ?: -1 //當且僅當?:左側(cè)為null時,才對右側(cè)表達式求值
//等價于
val l: Int = if (b != null) b.length else -1
因為在Kotlin中throw,return都是表達式,所以也可在?:右側(cè),例如檢查函數(shù)參數(shù):
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
//...
}
5.!!操作符(!! Operator)
第三個選擇,是使用操作符!!,為NPE空指針異常的愛好者準備的, 讓編譯器不檢查null
如果b變量為null,就會拋出空指針異常NullPointerException(NPE)!
例如:
val l = b!!.length //如果b為null,會拋出空指針異常NullPointerException
6.過濾集合的可空元素-filterNotNull()
如果集合有可空類型元素的,要過濾非空元素,可用filterNotNull實現(xiàn):
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()
簡書:http://www.reibang.com/p/f2da6e3eb53e
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/74509791
GitHub博客:http://lioil.win/2017/07/05/Kotlin-null.html
Coding博客:http://c.lioil.win/2017/07/05/Kotlin-null.html