java 避免出現NullPointerException(空指針)的方法總結
Java應用中拋出的空指針異常是解決空指針的最好方式,也是寫出能順利工作的健壯程序的關鍵。俗話說“預防勝于治療”,對于這么令人討厭的空指針異常,這句話也是成立的。值得慶幸的是運用一些防御性的編碼技巧,跟蹤應用中多個部分之間的聯系,你可以將Java中的空指針異常控制在一個很好的水平上。順便說一句,這是Javarevisited上的第二個空指針異常的帖子。在上個帖子中我們討論了Java中導致空指針異常的常見原因,而在本教程中我們將會學習一些Java的編程技巧和最佳實踐。這些技巧可以幫助你避免Java中的空指針異常。遵從這些技巧同樣可以減少Java代碼中到處都有的非空檢查的數量。作為一個有經驗的Java程序員,你可能已經知道其中的一部分技巧并且應用在你的項目中。但對于新手和中級開發人員來說,這將是很值得學習的。順便說一句,如果你知道其它的避免空指針異常和減少空指針檢查的Java技巧,請和我們分享。
這些都是簡單的技巧,很容易應用,但是對代碼質量和健壯性有顯著影響。根據我的經驗,只有第一個技巧可以顯著改善代碼質量。如我之前所講,如果你知道任何避免空指針異常和減少空指針檢查的Java技巧,你可以通過評論本文來和分享。
1) 從已知的String對象中調用equals()和equalsIgnoreCase()方法,而非未知對象。
總是從已知的非空String對象中調用equals()方法。因為equals()方法是對稱的,調用a.equals(b)和調用b.equals(a)是完全相同的,這也是為什么程序員對于對象a和b這么不上心。如果調用者是空指針,這種調用可能導致一個空指針異常
1
2
3
4
5
6
7
8
9
10
11
|
Object unknownObject = null ; //錯誤方式 – 可能導致 NullPointerException if (unknownObject.equals( "knownObject" )){ System.err.println( "This may result in NullPointerException if unknownObject is null" ); } //正確方式 - 即便 unknownObject是null也能避免NullPointerException if ( "knownObject" .equals(unknownObject)){ System.err.println( "better coding avoided NullPointerException" ); } |
這是避免空指針異常最簡單的Java技巧,但能夠導致巨大的改進,因為equals()是一個常見方法。
2) 當valueOf()和toString()返回相同的結果時,寧愿使用前者。
因為調用null對象的toString()會拋出空指針異常,如果我們能夠使用valueOf()獲得相同的值,那寧愿使用valueOf(),傳遞一個null給valueOf()將會返回“null”,尤其是在那些包裝類,像Integer、Float、Double和BigDecimal。
1
2
3
|
BigDecimal bd = getPrice(); System.out.println(String.valueOf(bd)); //不會拋出空指針異常 System.out.println(bd.toString()); //拋出 "Exception in thread "main" java.lang.NullPointerException" |
3) 使用null安全的方法和庫 有很多開源庫已經為您做了繁重的空指針檢查工作。其中最常用的一個的是Apache commons 中的StringUtils。你可以使用StringUtils.isBlank(),isNumeric(),isWhiteSpace()以及其他的工具方法而不用擔心空指針異常。
1
2
3
4
5
6
7
8
9
10
11
|
//StringUtils方法是空指針安全的,他們不會拋出空指針異常 System.out.println(StringUtils.isEmpty( null )); System.out.println(StringUtils.isBlank( null )); System.out.println(StringUtils.isNumeric( null )); System.out.println(StringUtils.isAllUpperCase( null )); Output: true true false false |
但是在做出結論之前,不要忘記閱讀空指針方法的類的文檔。這是另一個不需要下大功夫就能得到很大改進的Java最佳實踐。
4) 避免從方法中返回空指針,而是返回空collection或者空數組。
這個Java最佳實踐或技巧由Joshua Bloch在他的書Effective Java中提到。這是另外一個可以更好的使用Java編程的技巧。通過返回一個空collection或者空數組,你可以確保在調用如size(),length()的時候不會因為空指針異常崩潰。Collections類提供了方便的空List,Set和Map: Collections.EMPTY_LIST,Collections.EMPTY_SET,Collections.EMPTY_MAP。這里是實例。
1
2
3
4
|
public List getOrders(Customer customer){ List result = Collections.EMPTY_LIST; return result; } |
你同樣可以使用Collections.EMPTY_SET和Collections.EMPTY_MAP來代替空指針。
5) 使用annotation@NotNull 和 @Nullable
在寫程序的時候你可以定義是否可為空指針。通過使用像@NotNull和@Nullable之類的annotation來聲明一個方法是否是空指針安全的。現代的編譯器、IDE或者工具可以讀此annotation并幫你添加忘記的空指針檢查,或者向你提示出不必要的亂七八糟的空指針檢查。IntelliJ和findbugs已經支持了這些annotation。這些annotation同樣是JSR 305的一部分,但即便IDE或工具中沒有,這個annotation本身可以作為文檔。看到@NotNull和@Nullable,程序員自己可以決定是否做空指針檢查。順便說一句,這個技巧對Java程序員來說相對比較新,要采用需要一段時間。
6) 避免你的代碼中不必要的自動包裝和自動解包。
且不管其他如創建臨時對象的缺點,如果wrapper類對象是null,自動包裝同樣容易導致空指針異常。例如如果person對象沒有電話號碼的話會返回null,如下代碼會因為空指針異常崩潰。
1
2
|
Person ram = new Person( "ram" ); int phone = ram.getPhone(); |
當使用自動包裝和自動解包的時候,不僅僅是等號,< > 同樣會拋出空指針異常。你可以通過這篇文章來學習更多的Java中的自動包裝和拆包的陷阱。
7) 遵從Contract并定義合理的默認值。
在Java中避免空指針異常的一個最好的方法是簡單的定義contract并遵從它們。大部分空指針異常的出現是因為使用不完整的信息創建對象或者未提供所有的依賴項。如果你不允許創建不完整的對象并優雅地拒絕這些請求,你可以在接下來的工作者預防大量的空指針異常。類似的,如果對象允許創建,你需要給他們定義一個合理的默認值。例如一個Employee對象不能在創建的時候沒有id和name,但是是否有電話號碼是可選的。現在如果Employee沒有電話號碼,你可以返回一個默認值(例如0)來代替返回null。但是必須謹慎選擇,喲有時候檢查空指針比調用無效號碼要方便。同樣的,通過定義什么可以是null,什么不能為null,調用者可以作出明智的決定。failing fast或接受null同樣是一個你需要進行選擇并貫徹的,重要的設計決策
8)定義數據庫中的字段是否可為空。
如果你在使用數據庫來保存你的域名對象,如Customers,Orders 等,你需要在數據庫本身定義是否為空的約束。因為數據庫會從很多代碼中獲取數據,數據庫中有是否為空的檢查可以確保你的數據健全。在數據空中維護null約束同樣可以幫助你減少Java代碼中的空指針檢查。當從數據庫中加載一個對象是你會明確,哪些字段是可以為null的,而哪些不能,這可以使你代碼中不必要的!= null檢查最少化。
9) 使用空對象模式(Null Object Pattern)
還有一種方法來避免Java中的空指針異常。如果一個方法返回對象,在調用者中執行一些操作,例如Collection.iterator()方法返回迭代器,其調用者執行遍歷。假設如果一個調用者并沒有任何迭代器,其可以返回空對象(Null object)而非null。空對象是一個特殊的對象,其在不同的上下文中有不同的意義。例如一個空的迭代器調用hasNext()返回false時,可以是一個空對象。同樣的在返回Container和Collection類型方法的例子中,空對象可以被用來代替null作為返回值。我打算另寫一篇文章來講空對象模式,分享幾個Java空對象的例子。
這就是全部了,這是幾個易于遵從的避免空指針異常的Java技巧和最佳實踐。你可以欣賞到這些技巧將非常有用,且不太難實現。如果你有其他比秒這個異常的技巧,而又沒包含在這里,請通過評論來和我們分享,我將收錄在這里。
如有疑問請留言或者到本站社區交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
原文鏈接:http://blog.csdn.net/lylwo317/article/details/51198339