一、在空安全推出之前,靜態類型系統允許所有類型的表達式中的每一處都可以有 null。
從類型理論的角度來說,Null 類型被看作是所有類型的子類;
類型會定義一些操作對象,包括 getters、setters、方法和操作符,在表達式中使用。
如果是 List 類型,您可以對其調用 .add() 或 []。
如果是 int 類型,您可以對其調用 +。
但是 null 值並沒有它們定義的任何一個方法。
所以當 null 傳遞至其他類型的表達式時,任何操作都有可能失敗。
這就是空引用的症結所在—所有錯誤都來源於嘗試在 null 上查找一個不存在的方法或屬性。
二、非空和可空類型
空安全通過修改了類型的層級結構,從根源上解決了這個問題。Null 類型仍然存在,但它不再是所有類型的子類。現在的類型層級看起來是這樣的:
既然 Null 已不再被看作所有類型的子類,那么除了特殊的 Null 類型允許傳遞 null 值,其他類型均不允許。
我們已經將所有的類型設置為默認不可空的類型。如果您的變量是 String 類型,它必須包含一個字符串。這樣一來,我們就修復了所有的空引用錯誤。
三、引入空安全后的類型頂層設計
四、空安全的適配
類型默認是非空的,可以添加 ? 變為可空的。
可選參數必須是可空的或者包含默認值的。您可以使用 required 來構建一個非可選命名參數。非空的全局變量和靜態字段必須在聲明時被初始化。實例的非空字段必須在構造體開始執行前被初始化。
如果接收者為 null,那么在其避空運算符之后的鏈式方法調用都會被截斷。我們引入了新的空判斷級聯操作符 (?..) 及索引操作符 (?[])。后綴空斷言“重點”操作符 (!) 可以將可空的操作對象轉換為對應的非空類型。
新的流程分析,讓您更安全地將可空的局部變量和參數,轉變為可用的非空類型。它同時還對類型提升、遺漏的返回、不可達的代碼以及變量的初始化,有着更為智能的規則。
late修飾符以在運行時每次都進行檢查的高昂代價,讓您在一些原本無法使用的地方,能夠使用非空類型和 final。它同時提供了對字段延遲初始化的支持。
List 類現在不再允許包含未初始化的元素。