如何在java項(xiàng)目中避免出現(xiàn)空指針?相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
成都創(chuàng)新互聯(lián)公司主營平南網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,app開發(fā)定制,平南h5小程序開發(fā)搭建,平南網(wǎng)站營銷推廣歡迎平南等地區(qū)企業(yè)咨詢
java 避免出現(xiàn)NullPointerException(空指針)的方法總結(jié)
Java應(yīng)用中拋出的空指針異常是解決空指針的最好方式,也是寫出能順利工作的健壯程序的關(guān)鍵。俗話說“預(yù)防勝于治療”,對于這么令人討厭的空指針異常,這句話也是成立的。值得慶幸的是運(yùn)用一些防御性的編碼技巧,跟蹤應(yīng)用中多個部分之間的聯(lián)系,你可以將Java中的空指針異常控制在一個很好的水平上。順便說一句,這是Javarevisited上的第二個空指針異常的帖子。在上個帖子中我們討論了Java中導(dǎo)致空指針異常的常見原因,而在本教程中我們將會學(xué)習(xí)一些Java的編程技巧和最佳實(shí)踐。這些技巧可以幫助你避免Java中的空指針異常。遵從這些技巧同樣可以減少Java代碼中到處都有的非空檢查的數(shù)量。作為一個有經(jīng)驗(yàn)的Java程序員,你可能已經(jīng)知道其中的一部分技巧并且應(yīng)用在你的項(xiàng)目中。但對于新手和中級開發(fā)人員來說,這將是很值得學(xué)習(xí)的。順便說一句,如果你知道其它的避免空指針異常和減少空指針檢查的Java技巧,請和我們分享。
這些都是簡單的技巧,很容易應(yīng)用,但是對代碼質(zhì)量和健壯性有顯著影響。根據(jù)我的經(jīng)驗(yàn),只有第一個技巧可以顯著改善代碼質(zhì)量。如我之前所講,如果你知道任何避免空指針異常和減少空指針檢查的Java技巧,你可以通過評論本文來和分享。
1) 從已知的String對象中調(diào)用equals()和equalsIgnoreCase()方法,而非未知對象。
總是從已知的非空String對象中調(diào)用equals()方法。因?yàn)閑quals()方法是對稱的,調(diào)用a.equals(b)和調(diào)用b.equals(a)是完全相同的,這也是為什么程序員對于對象a和b這么不上心。如果調(diào)用者是空指針,這種調(diào)用可能導(dǎo)致一個空指針異常
Object unknownObject = null; //錯誤方式 – 可能導(dǎo)致 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技巧,但能夠?qū)е戮薮蟮母倪M(jìn),因?yàn)閑quals()是一個常見方法。
2) 當(dāng)valueOf()和toString()返回相同的結(jié)果時,寧愿使用前者。
因?yàn)檎{(diào)用null對象的toString()會拋出空指針異常,如果我們能夠使用valueOf()獲得相同的值,那寧愿使用valueOf(),傳遞一個null給valueOf()將會返回“null”,尤其是在那些包裝類,像Integer、Float、Double和BigDecimal。
BigDecimal bd = getPrice(); System.out.println(String.valueOf(bd)); //不會拋出空指針異常 System.out.println(bd.toString()); //拋出 "Exception in thread "main" java.lang.NullPointerException"
3) 使用null安全的方法和庫 有很多開源庫已經(jīng)為您做了繁重的空指針檢查工作。其中最常用的一個的是Apache commons 中的StringUtils。你可以使用StringUtils.isBlank(),isNumeric(),isWhiteSpace()以及其他的工具方法而不用擔(dān)心空指針異常。
//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
但是在做出結(jié)論之前,不要忘記閱讀空指針方法的類的文檔。這是另一個不需要下大功夫就能得到很大改進(jìn)的Java最佳實(shí)踐。
4) 避免從方法中返回空指針,而是返回空collection或者空數(shù)組。
這個Java最佳實(shí)踐或技巧由Joshua Bloch在他的書Effective Java中提到。這是另外一個可以更好的使用Java編程的技巧。通過返回一個空collection或者空數(shù)組,你可以確保在調(diào)用如size(),length()的時候不會因?yàn)榭罩羔槷惓1罎?。Collections類提供了方便的空List,Set和Map: Collections.EMPTY_LIST,Collections.EMPTY_SET,Collections.EMPTY_MAP。這里是實(shí)例。
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來聲明一個方法是否是空指針安全的?,F(xiàn)代的編譯器、IDE或者工具可以讀此annotation并幫你添加忘記的空指針檢查,或者向你提示出不必要的亂七八糟的空指針檢查。IntelliJ和findbugs已經(jīng)支持了這些annotation。這些annotation同樣是JSR 305的一部分,但即便IDE或工具中沒有,這個annotation本身可以作為文檔。看到@NotNull和@Nullable,程序員自己可以決定是否做空指針檢查。順便說一句,這個技巧對Java程序員來說相對比較新,要采用需要一段時間。
6) 避免你的代碼中不必要的自動包裝和自動解包。
且不管其他如創(chuàng)建臨時對象的缺點(diǎn),如果wrapper類對象是null,自動包裝同樣容易導(dǎo)致空指針異常。例如如果person對象沒有電話號碼的話會返回null,如下代碼會因?yàn)榭罩羔槷惓1罎ⅰ?/p>
Person ram = new Person("ram"); int phone = ram.getPhone();
當(dāng)使用自動包裝和自動解包的時候,不僅僅是等號,< > 同樣會拋出空指針異常。你可以通過這篇文章來學(xué)習(xí)更多的Java中的自動包裝和拆包的陷阱。
7) 遵從Contract并定義合理的默認(rèn)值。
在Java中避免空指針異常的一個最好的方法是簡單的定義contract并遵從它們。大部分空指針異常的出現(xiàn)是因?yàn)槭褂貌煌暾男畔?chuàng)建對象或者未提供所有的依賴項(xiàng)。如果你不允許創(chuàng)建不完整的對象并優(yōu)雅地拒絕這些請求,你可以在接下來的工作者預(yù)防大量的空指針異常。類似的,如果對象允許創(chuàng)建,你需要給他們定義一個合理的默認(rèn)值。例如一個Employee對象不能在創(chuàng)建的時候沒有id和name,但是是否有電話號碼是可選的。現(xiàn)在如果Employee沒有電話號碼,你可以返回一個默認(rèn)值(例如0)來代替返回null。但是必須謹(jǐn)慎選擇,喲有時候檢查空指針比調(diào)用無效號碼要方便。同樣的,通過定義什么可以是null,什么不能為null,調(diào)用者可以作出明智的決定。failing fast或接受null同樣是一個你需要進(jìn)行選擇并貫徹的,重要的設(shè)計決策
8)定義數(shù)據(jù)庫中的字段是否可為空。
如果你在使用數(shù)據(jù)庫來保存你的域名對象,如Customers,Orders 等,你需要在數(shù)據(jù)庫本身定義是否為空的約束。因?yàn)閿?shù)據(jù)庫會從很多代碼中獲取數(shù)據(jù),數(shù)據(jù)庫中有是否為空的檢查可以確保你的數(shù)據(jù)健全。在數(shù)據(jù)空中維護(hù)null約束同樣可以幫助你減少Java代碼中的空指針檢查。當(dāng)從數(shù)據(jù)庫中加載一個對象是你會明確,哪些字段是可以為null的,而哪些不能,這可以使你代碼中不必要的!= null檢查最少化。
9) 使用空對象模式(Null Object Pattern)
還有一種方法來避免Java中的空指針異常。如果一個方法返回對象,在調(diào)用者中執(zhí)行一些操作,例如Collection.iterator()方法返回迭代器,其調(diào)用者執(zhí)行遍歷。假設(shè)如果一個調(diào)用者并沒有任何迭代器,其可以返回空對象(Null object)而非null??諏ο笫且粋€特殊的對象,其在不同的上下文中有不同的意義。例如一個空的迭代器調(diào)用hasNext()返回false時,可以是一個空對象。同樣的在返回Container和Collection類型方法的例子中,空對象可以被用來代替null作為返回值。我打算另寫一篇文章來講空對象模式,分享幾個Java空對象的例子。
看完上述內(nèi)容,你們掌握如何在java項(xiàng)目中避免出現(xiàn)空指針的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!