2.1 空值和本書中的偽代碼慣例
在我們觀察代碼示例之前,解釋本書中偽代碼處理控制的慣例十分重要。
許多編程語言都有某個值(或引用/指針)缺失的概念。編程語言的內置方法往往使用空值(Null)。歷史上,空值游走于兩個極端之間:有時非常好用,有時又會帶來難以置信的問題。
● 空值之所以有用,是因為某個事物不存在的情況經常出現:某個值未提供或者某個函數不能提供預期的結果。
● 空值之所以會帶來問題,是因為一個值能不能為空并不總是顯而易見的,工程師經常在訪問變量之前忘記檢查它是否為空。這往往導致出錯。你以前可能見過NullPointerException(空指針異常)、NullReferenceException(空引用異常)或Cannot read property of null(無法讀取空屬性)等錯誤信息,次數或許比你記得的要多。
由于空值可能帶來問題,因此你有時候會看到一些建議,倡導絕不使用它們,或者至少絕不會從函數中返回空值。這當然有助于避免空值的問題,但在實踐中,遵循這個建議需要采用許多編程技巧。
幸運的是,近年來,“空值安全”〔也稱為“無效值安全”(void safety)〕的思路越來越受到關注。這能確保任何可能為空的變量或返回值有相應的標識,編譯器將強制要求必須事先檢查其非空后才能使用。
近年來出現的大部分重要的新編程語言都支持空值安全。在C#等編程語言的較新版本中,也可以選擇啟用該功能,甚至有辦法將其改造成類似Java這樣的編程語言。如果我們使用的編程語言支持空值安全,那么利用這一特性可能是個好主意。
如果我們使用的編程語言不支持空值安全,那么使用可選類型來代替空值是比較好的做法。許多編程語言都支持這一特性,包括Java、Rust(稱為Option)和C++(不過針對C++需要考慮一些細微的差別,我們在附錄B中介紹)。即使在不以標準特性形式支持空值安全的編程語言中,往往也有增添這種支持的第三方工具。
本書中的偽代碼慣例假設支持空值安全。默認情況下,變量、函數參數和返回類型都不可以是空值。但如果類型以“?”為后綴,就意味著它可以為空,編譯器將不強制先檢查其是為非空就可以使用。下面的代碼片段展示了使用空值安全的偽代碼:
Element? getFifthElement(List<Element> elements) { ←--- Element?中的“?”表示返回類型可以為空 if (elements.size() < 5) { return null; ←--- 當我們無法獲得該值時返回空值 } return elements[4]; }
如果我們使用的編程語言不支持空值安全,但是又想用可選類型編寫這個函數,那么下面這個代碼片段展示了改寫的方法:
Optional<Element> getFifthElement(List<Element> elements) { ←--- 返回類型是可選元素 if (elements.size() < 5) { return Optional.empty(); ←--- 返回Optional.empty(),代替空值 } return Optional.of(elements[4]); }
如果你想了解更多關于空值安全和可選類型的知識,請參考附錄B。