空指針的問題可以追溯到計算法發(fā)展史時期脚草,同時空指針異常的情況也很多造锅,甚至在程序運行階段也無法避免空指針的情況。那么输涕,在編碼層面音婶,我們需要注意哪些呢?
確認調用的的每個變量都已經被初始化
這點說起來很簡單莱坎,但事實上隨著業(yè)務的發(fā)展項目代碼也會越來越龐大衣式。這時候方法之間調用的關系也會越來越復雜,很難避免使用到的方法都已經明確被初始化檐什。
所以這塊單獨放在這里碴卧,需要我們在編碼的時候重點考慮變量存在的可能性,這其實大體上基于自己的實際編碼經驗乃正。
盡量使用明確的值調用
如果已經明確某個變量(常量)的值住册,那么是可以安全調用它的方法的。例如對比下面的幾行代碼:
String a = null;
a.equal("b"); // 會產生空指針異常
"b".equal(a); // 推薦的寫法
很明顯使用常量去做調用這代碼會更健壯一些瓮具。
盡量避免在函數中返回 NULL
當如果在編寫方法中考慮返回 NULL荧飞,這個時候則需要冷靜下是否真的需要這樣子做。因為搭综,通常來說會有比返回 NULL 更好的處理方式。
自動裝箱需謹慎
自動裝箱確實為編寫程序帶來很多方便划栓,但我們在編程時候也不能濫用自動裝箱兑巾。
比如,下面這個程序依然存在空指針異常隱患:
Person jack = new Person("jack");
int weight = jack.getWeight();
這種異常在我們使用一些 ORM 框架中會碰到忠荞,如果數據庫對應的對象并不存在該值蒋歌,而我們又在類中使用了一個基本類型與之對應,依然就會拋出空指針異常委煤。在這種情況下就盡量使用包裝類來對應堂油,并且在使用該值時候先判斷是否為空。
遍歷謹防集合為空
for (int num : list) {
// for each num in list
}
及時驗證外部數據
在代碼運行的過程中碧绞,尤其在解析外部數據的時候可能會引發(fā)影響不到的問題府框。例如下面的 Json 數據
{"name": null, age: 28}
如果不處理完善,直接使用 name 屬性也會導致空指針的問題讥邻。
使用第三方庫加強驗證
很多第三方的 Common 庫都會有驗證空指針的方法迫靖,例如 Guava 中針對空指針的判斷有個單獨的包去處理院峡。
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
或者過濾 NULL 也會更加的方便
Joiner joiner = Joiner.on("").skipNulls();
return joiner.join("Harry", null, "Ron", "Hermione");
使用 @NotNull 或 @Nullable 注解
強烈建議多使用注解來增加代碼的可讀性,例如多增加 @NotNull 或 @Nullable 注解系宜,也
可以加強代碼靜態(tài)檢查方面可能會造成空指針的可能性照激,具體可以參見這里。
使用 Java8 的 Optional
很多「現(xiàn)代」語言都會有針對變量為空的可選鏈式判斷盹牧,例如
Grovvy
語言有一個 ?.
的操作符俩垃,可以安全地處理潛在可能的空引用(據說 Java7 曾被建議引入這個但是并沒有發(fā)布)。它是這么用的:
String version = computer?.getSoundcard()?.getUSB()?.getVersion();
雖然 Java 看起來非常的保守汰寓,但好在 Java8 中增加了 Option[T]
這個對象包來代表類型 T 的某一個值存在或者沒有口柳。
那么上面的代碼可以寫成
String name = computer.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
看起來似乎有點麻煩,但相信我你會愛上這樣的寫法踩寇,具體可以參見這里啄清。