历史上的今天:编程语言中null引用的十亿美元错误
這是Jerry 2021年的第 10 篇文章,也是汪子熙公眾號總共第 281 篇原創文章。
今天是2021年1月17日,星期日,臘月初五。
Jerry之前收到CSDN社區贈送的新年禮物,一本臺歷:《了不起的程序員》,
其中1月16日,17日兩天的篇幅,都在介紹托尼·霍爾(Tony Hoare), 計算機科學家,因程序設計語言定義與設計方面的杰出貢獻獲得1980年的圖靈獎。快速排序算法的發明者。
如果想查看用ABAP實現的8種排序算法的源代碼,可以查看Jerry之前的文章:
Jerry 2017年的五一小長假:8種經典排序算法的ABAP實現
本文不會討論霍爾發明的快速排序算法,而是介紹另一個來自霍爾,如今仍然被程序員在編程語言中廣泛使用的一個設計:null引用。
null引用被霍爾稱為"十億美元錯誤",是霍爾1965年設計ALGOL W語言時提出的。
《Java實戰》中提到,在Java程序開發中使用null會帶來理論和實際操作上的種種問題:
- 它是錯誤之源
- 會使你的代碼膨脹
- 自身毫無意義
- 破壞了Java的哲學
- 在Java的類型系統上開了口子
霍爾的名言:
我把它叫做我的“十億美元錯誤”,就是在1965年發明了空引用… 我無法抵擋放進一個空引用的誘惑,僅僅是因為實現起來非常容易。
引入了空引用的編程語言,在訪問引用之前,需要顯式檢查引用是否有效。
Java
下圖第46行代碼定義的print方法,輸入參數是一個類型為Integer的引用。在調用引用之前,需要先判斷其是否是空引用,否則程序執行時就會出現運行時異常。
ABAP
使用CHECK X IS NOT INITIAL進行防御,如果X為空引用,則不會執行CHECK語句的下一條語句。
嚴謹的德國人,在霍爾教授null引用的基礎上,又設計出IS BOUND, IS NOT INITIAL和IS ASSIGNED這幾種判斷邏輯:
SAP ABAP一組關鍵字 IS BOUND, IS NOT INITIAL和IS ASSIGNED的用法辨析
JavaScript
第10行的print方法內部,用&&操作符的短路邏輯(short-circuit)特性來實現空引用的檢測:如果傳入的oPrinter是空引用,則不會執行&&后面的print調用。
而TypeScript提供的可選鏈(Optional Chaining),則可以在語言層面優雅地避免這個問題。
下面的TypeScript代碼,使用問號構造了一個可選鏈。如果a為空,則表達式a?.b直接返回undefined給變量val,而不會試圖去執行a.b
上圖TypeScript代碼,編譯之后生成的JavaScript代碼如下圖所示,我們可以把TypeScript的可選鏈看成JavaScript用三元表達式實現的語法糖。
為了減輕Java程序員每次使用引用之前,顯式進行非空檢查的工作量,Java 8引入了一個新的工具類:Optional.
Optional僅僅是一個不含任何業務邏輯的包裹類,其value字段指向了真正的業務類。
下圖是一個使用Optional工具類的例子,第11行的filter方法,傳入的是一個通過Lambda Function實現的過濾條件。這行語句的語義是,對anotherName包含的字符串,進行過濾操作,檢查another實例的value字段存儲的引用,是否滿足過濾條件(字符串長度小于6):
Optional.filter方法,無論過濾條件是否滿足,返回的類型均為Optional,便于鏈式調用。
我第10行傳入Optional對象的字符串,顯然長度遠遠大于6,所以filter方法返回一個新的Optional對象,其value字段為null.
對于filter調用返回的Optional對象,我們可以繼續調用orElse,設置一個默認值。下圖第14行用orElse實現的邏輯,語義是:如果shortName包裹的value字段為空,則返回orElse方法傳入的默認值。
Java 8的Optional工具類并不像TypeScript的可選鏈一樣,后者是語言層面提供的特性,而Optional僅僅是開發包里的一個工具類。
比如Optional的靜態方法of,其實現僅僅是新建一個Optional對象,去包裹傳入的value引用:
orElse方法,內部實現也是一個簡單的三元表達式。
看這樣一個極端的例子:
Outer類有一個字段nested,類型為Nested類。Nested類有一個字段inner,類型為Inner類。Inner類包含了字段foo,類型為String,值為Jerry:
如果想從Outer類的實例出發,寫一段比較健壯的代碼,打印出深藏在Inner類里的foo字段,常規的寫法和使用Optional的寫法分別位于下圖test1和test2方法,大家可以比較下,更喜歡哪一種?
值得一提的是,類似Java Optional.orElse方法,在ABAP里也存在基于語言層面的支持。
下圖是ABAP 740的新語法:
上面的新語法,翻譯成傳統的ABAP代碼如下:
由此可見,新的ABAP內表讀取的語法比較簡潔,能少寫3行代碼。
但是新語法有一個缺陷:如果it_data內表,不存在object_ext的值為cl_crm_prodil_bo_names=>gc_prod_root的記錄,此時程序執行會被終止,拋出異常CX_SY_ITAB_LINE_NOT_FOUND:
當然針對這種情況,ABAP也有對應的解決方案。
下圖測試代碼第17行會拋出異常,而19行不會。從語義上容易理解:如果內表lt_data里不存在name為Spring2的記錄,則返回開發者使用DEFAULT VALUE關鍵字指定的一個結構,作為默認值。
第19行執行完畢后,結構ls3的name字段為SpringInvalid, value為999.
本文從霍爾教授1965年提出的null引用作為切入點,向大家分享了Jerry工作中同空引用打交道的一些經歷,感謝閱讀。
ABAP專題
-
Jerry的ABAP, Java和JavaScript亂燉
-
ABAP開發人員未來應該學些什么
-
Jerry 2017年的五一小長假:8種經典排序算法的ABAP實現
-
Jerry的ABAP原創技術文章合集
-
300行ABAP代碼實現一個最簡單的區塊鏈原型
-
使用Java+SAP云平臺+SAP Cloud Connector調用ABAP On-Premise系統里的函數
-
在SAP云平臺的CloudFoundry環境下消費ABAP On-Premise OData服務
-
ABAP vs Java, 蛙泳 vs 自由泳
-
聊聊C語言和ABAP
-
動手使用ABAP Channel開發一些小工具,提升日常工作效率
-
我用ABAP做過的那些無聊的事情
-
不喜歡SAP GUI?那試試用Eclipse進行ABAP開發吧
-
使用Visual Studio Code編寫和激活ABAP代碼
-
你的ABAP程序給佛祖開過光么?來試試Jerry這個小技巧
-
在SAP云平臺ABAP編程環境上編寫第一段ABAP程序
-
SAP官方發布的ABAP編程規范
-
ABAP Code Inspector那些隱藏的功能,您都知道嗎?
-
還在用ABAP進行SAP產品的二次開發?來了解下這種全新的二次開發理念吧
-
ABAP Netweaver體內的那些寄生式編程語言
-
從SAP社區上的一篇博客開始,聊聊SAP產品命名背后的那份情懷
-
云端的ABAP Restful服務開發
-
如何在SAP云平臺ABAP編程環境里把CDS view暴露成OData服務
-
使用abapGit在ABAP On-Premises系統和SAP云平臺ABAP環境之間進行代碼傳輸
-
30分鐘用Restful ABAP Programming模型開發一個支持增刪改查的Fiori應用
-
Jerry帶您了解Restful ABAP Programming模型系列之二:Action和Validation的實現
-
Jerry帶您了解Restful ABAP Programming模型系列之三:云端ABAP應用調試
-
SAP云平臺上的ABAP編程環境里如何消費第三方服務
-
ABAP開發者上云的時候到了 - 現在大家可以免費使用SAP云平臺ABAP環境的試用版了
-
學而不思則罔 - SAP云平臺ABAP編程環境的由來和適用場景
-
SAP云平臺里的三叉戟應用
-
如何基于Restful ABAP Programming模型開發并部署一個支持增刪改查的Fiori應用
-
SAP 2019 TechEd Key Note解讀:云時代下SAP從業人員如何做二次開發?
-
有哪些ABAP關鍵字和語法,到了ABAP云環境上就沒辦法用了?
-
ABAP開發環境終于支持以駝峰命名法自動格式化ABAP變量名了
-
利用ABAP 740的新關鍵字REDUCE完成一個實際工作任務
-
一段讓人瑟瑟發抖的ABAP代碼
-
昨日萬圣節ABAP怪獸級代碼謎團,公布答案啦
-
介紹一種在ABAP內核態進行內表高效拷貝的方法
-
使用SAP Cloud Application Programming模型開發OData的一個實際例子
-
當ABAP遇見普羅米修斯
-
使用ABAP繪制可伸縮矢量圖
-
ABAP開發環境語法高亮的那些事兒
-
SAP錯誤消息調試之七種武器:讓所有的錯誤消息都能被定位
-
使用ABAP操作Excel的幾種方法
-
SAP GUI里的收藏夾事務碼管理工具
-
SAP GUI和Windows注冊表
-
有了Debug權限就能干壞事?小心了,你的一舉一動盡在系統監控中
-
ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX這些東東是什么鬼
-
實現ABAP條件斷點的三種方式
-
使用SAT跟蹤監控從瀏覽器打開的SAP應用的性能和調用棧
-
一個13年ABAP老兵的建議:了解這些基礎知識,對ABAP開發有百利而無一害
-
SAP ABAP Netweaver容器化, 不可能完成的任務嗎?
-
SAP產品增強技術回顧
-
SAP API開發方法大全
-
淺談Java和SAP ABAP的靜態代理和動態代理,以及ABAP面向切面編程的嘗試
-
SAP ABAP應用服務器的HTTP響應狀態碼(Status Code)
-
SAP ABAP里存在Java List這種集合工具類么?CL_OBJECT_COLLECTION了解一下
-
ABAP面試題系列:寫一組會出現死鎖(Deadlock)的ABAP程序
-
SAP ABAP Netweaver服務器的標準登錄方式講解
-
SAP ABAP關鍵字語法圖和ABAP代碼自動生成工具Code Composer
-
SAP ABAP SM50的另類用途 - ABAP工作進程對數據庫表讀取操作的檢測
-
關于SAP ABAP字符變量和字符串變量字符個數的一個知識點,和一個血案
-
SAP ABAP一組關鍵字 IS BOUND, IS NOT INITIAL和IS ASSIGNED的用法辨析
-
SAP ABAP和Java里的弱引用(WeakReference)和軟引用(SoftReference)
-
SAP AMDP介紹 - ABAP托管的HANA數據庫過程
-
給你的ABAP對象打上標簽(Tag)
更多Jerry的原創文章,盡在:“汪子熙”:
總結
以上是生活随笔為你收集整理的历史上的今天:编程语言中null引用的十亿美元错误的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Stability AI 连扔两个王炸,
- 下一篇: 华为p30pro耳机型号