原文地址:http://www.codeproject.com/Articles/787668/Why-We-Should-Love-null?msg=4874666#xx4874666xx
譯者注:首先,中秋節快樂!
本文算是相對少見的一類話題:對null這個特殊元素尋根究底,追根其來源,講述其現狀,更重要的是探討其引發的問題的解決方案。文章很長,我分五部分譯出,也感謝大家的耐心!??
本篇文章為一篇,主要探討null的來源與尋常遇到的問題情況。
? ??
在軟件發展的歷程中,null就像一個幽靈,給人們帶來了無數的問題。如今,null幾乎就等同于“巨大財產損失的BUG”。所以就有很多開發人員想盡一切辦法避免null的出現,比如有人就采用“返回0,而不返回NULL”來處理,也有人采用空對象模式(NullObject Pattern),還有人采用Optional/Maybe 模式。
你覺得在開發中該用這些方法?它們真保證達到一個預期可用性的軟件嗎?抑或還有別的更好的解決方案?這就是這篇文章想要回答的問題。
太多開發人員討厭null,甚至是恨。
null正是臭名昭著的空指針錯誤(即JAVA中空指針異常)的罪魁禍首。
Manchester 學校的計算機系教授?John Sargeant 這么談到:
在JAVA程序運行時,空指針異常無疑是目前最常見的錯誤了。
帶有一點諷刺意味的來說,在JAVA中,空指針異常是唯一一個被人們授予了縮寫名的異常:NPE。所以如果你和一個JAVA的開發人員說“這段代碼里到處都有NPE”,他/她一定能明白你的意思。
(譯者注:中間這里作者有一段比較重復的話..我這里略掉,直入正題!)
好了,有人要問了:“null如此可恨,為何這篇文章還要我們去愛TA”?
別著急,且聽我一一道來。
在現實生活中,對于“無”的概念,我們有千千萬萬中表示方法。我可以舉幾個最簡單的列子,哪怕是小孩子也能看懂:
· 冰箱里沒有巧克力了(There is no chocolate in the fridge. )
· Fred并沒有一輛自行車(Fred doesn't have a bicycle.)
·?教室里空空如也(The class room is empty.)
所以我們可以清晰的認識到:任何程序語言(甚至可以擴展到任何需要展示信息的技術)都必須有一種方式來表達“無”(Nothing)。
在1965年的時候,Tony Hoare想到了一種簡單而聰明的辦法來在計算機領域表示Nothing——你一定猜到了,那就是“null”;
其他語言也有用到一些其他關鍵詞來表示同樣的意思,比如nil,void,none 或者nothing。
請不要忽視null的地位——它真的是一個極其重要甚至奇特的概念。
自從有了null,我們就可以這樣來描述事物了:
·?Alice的生日還沒有存到數據庫里?(alice.birth_date = null)
·?這個顧客還沒有下單(customer.order_list = null)
·?這個操作順利完成,沒有出現任何錯誤。(error = null)
·?我們不知道冰箱里有沒有啤酒(fridge.beer = null)
我們先來看看null的一個簡單的例子:
如果Alice有一個Email,那么代碼大概是這樣:
String email = "alice@company.com";
而如果她沒有Email(或者地址不知道),那代碼就成了這樣:
String email = null;
然后我們檢查她的Email地址是否真的存在,同時進行一點對應的處理:
if ( email != null ) {
System.out.println ( "Alice's email address is " + email );
} else {
System.out.println ( "Alice doesn't have an email address." );
}
怎么樣,是不是簡單,實際,上檔次!(譯者:很遺憾不是高大上= = )
既然挺好的,那..問題在哪呢?為什么null會導致這么多問題?
其實有一個非常簡單而又獨一無二的答案:
有時候,我們(開發人員)就是單純忘記考慮某個值為null的情況了
對吧,多么簡單而充分的理由,而且往往就像這樣:
if ( you_never_forget_to_check_for_null ) {
System.out.println ( "Bravo!!!" );
System.out.println ( "Enjoy and be proud of an application free of null pointer errors." );
}
而且更加不幸的是,這種“健忘”在實際開發中比比皆是。這樣對于層出不窮的空指針錯誤,咱們也就怪不怪了吧?相比小問題,有些BUG甚至直接導致災難性的后果。
假設就繼續以上述代碼為例,我們忘記檢查Alice的郵件地址是否存在了,直接無視了if判斷然后直接寫:
System.out.println ( "Alice's email address is " + email );
這時候就有兩個非常重要的問題:
如果email變量為null,本應該出現什么狀況?實際又出現了什么狀況?
至少有3種情況有可能發生:
程序無視了null然后這樣打印:
Alice's email address is
程序直接以“null”打印:
Alice's email address is null
程序直接拋出一個空指針異常(NullPointerException)
這是一個非常小的null場景。盡管如此,但要搞清楚它到底會出現什么情況,還是要通過這些小測試來嘗試,因為它往往都依賴于我們所采用的開發語言以及編譯器。很多經驗豐富的程序猿(包括我)在遇到這種情況的時候都會絞盡腦汁地去預測它可能出現的情況,而且毫不猶豫。這里我用了JAVA 8 ,然后非常迫切的等待這個結果。結果就是這樣:
Alice's email address is null
有人肯定會覺得:“這挺好的啊,系統告知我們這個email是未知的了,而且更重要的是沒有空指針異常出現。”
好了,我們剛剛上面使用了一個例子,而且我們想盡量的避免,或者壓制住空指針錯誤的產生。
不過有一個疑問:這樣做好嗎?去想辦法躲避空指針,這種做法真能提高代碼的質量和軟件的可用性嗎?我們的開發中確實很需要這種技術嗎?
在回答這個問題之前:我們先來看看目前比較流行的“防null大法”
1. 采用0來代替null
2. 使用空對象模式
3. 使用Optional/Maybe模式
【未完待續...下篇開始將會對這三種方式進行深入講解】