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