一、背景
程式員寫代碼經常被調侃為 “寫BUG”。
然而開發中遇到的其中一個主要 BUG 就是 空指針造成的。
很多人并不會認為預發空指針有多難,甚至有些人會認為自己如果寫代碼肯定會注意到。
最大的問題是,我們寫代碼時很多空指針的情況并不是直接發生的,而是被“傳遞”過來的,導緻沒有留意。
下面介紹幾種工作中可能不經意中寫出的,花式踩坑空指針異常的姿勢。
二、踩坑姿勢
2.1 自動拆箱空指針異常
如調用類似下面這種格式的二方服務接口,

如果不進行判空而直接使用,則很容易碰到空指針:
正确的使用姿勢應該是:
2.2 RPC接口傳回null
二方服務的批量查詢接口如果資料量大容易逾時,是以我們可以分批查詢,參加下面代碼:
看似沒啥問題,先将參數集合拆分成 多個小集合,然後調用傳入的接口查詢。
問題是,如果其中一批調用傳回了 null 會怎樣?
很可能發生空指針異常。
是以在合并前應該将結果為 null 的過濾掉。
三、預防
3.1 手冊
《阿裡巴巴 Java程式設計規範》 給出了空指針的一些常見場景:
傳回類型為基本資料類型,return 包裝資料類型的對象時,自動拆箱有可能産生 NPE
資料庫查詢結果可能為null
集合元素即使 isNotEmpty,取出資料元素可能為null
遠端調用傳回對象時,一律要求進行空指針判斷,防止 NPE
對于 Session 中擷取的資料,建議進行 NPE 檢查,避免空指針
級聯調用 obj.getA().getB().getC();一連串調用,易産生 NPE
3.2 源碼
Java 空指針異常的源碼注釋提供了 産生空指針的主要原因:
即
調用 null 對象的執行個體方法
通路或者修改 null 對象的屬性
擷取值為null 的數組長度
通路或修改值為 null 的二維數組的列
把 null 當做 Throwable 對象抛出
官方源碼列舉的幾種情況,更全面,更有參考價值。
四、預發空指針
4.1 作為接口提供方或者編寫者
編寫接口時
如果傳回值為集合類型,如果沒值盡量傳回空集合。
可以傳回Optional
4.2 作為接口的使用方
使用 commons-lang3 或者 guava的 字元串、對象、集合工具類判空
使用@Nonnull 注解等避免必傳字段前端傳null
五、總結
寫代碼時不要想當然,很多時候大意失荊州。
要了解常見的造成空指針的場景,開發時極力避免。
多看源碼注釋,會有更多發現。