如何在Java中優(yōu)雅地判空詳解
前言
整天都是在跟Java打交道。我在Java開(kāi)發(fā)中最常用的一段代碼就是用object != null在使用對(duì)象之前判斷是否為空。這么做是為了避免NullPointerException。但是我發(fā)現(xiàn)這樣檢測(cè)代碼實(shí)在是太丑了,而且及其不可讀。
那有沒(méi)有一種優(yōu)雅的替代方法呢?
判空災(zāi)難

作為搬磚黨的一族們,我們對(duì)判空一定再熟悉不過(guò)了,不要跟我說(shuō)你很少進(jìn)行判空,除非你喜歡NullPointerException。
不過(guò)NullPointerException對(duì)于很多猿們來(lái)說(shuō),也是Exception家族中最親近的一員了。

為了避免NullPointerException來(lái)找我們,我們經(jīng)常會(huì)進(jìn)行如下操作。
if (data != null) {
do sth.
}
如果一個(gè)類(lèi)中多次使用某個(gè)對(duì)象,那你可能要一頓操作,so:

“世界第九大奇跡”就這樣誕生了。Maybe你會(huì)想,項(xiàng)目中肯定不止你一個(gè)人會(huì)這樣一頓操作,然后按下Command+Shift+F,真相就在眼前:

What,我們有接近一萬(wàn)行的代碼都是在判空?

好了,接下來(lái),要進(jìn)入正題了。
NullObject模式
對(duì)于項(xiàng)目中無(wú)數(shù)次的判空,對(duì)代碼質(zhì)量整潔度產(chǎn)生了十分之惡劣的影響,對(duì)于這種現(xiàn)象,我們稱(chēng)之為“判空災(zāi)難”。
那么,這種現(xiàn)象如何治理呢,你可能聽(tīng)說(shuō)過(guò)NullObject模式,不過(guò)這不是我們今天的武器,但是還是需要介紹一下NullObject模式。
什么是NullObject模式呢?
In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral ("null") behavior. The null object design pattern describes the uses of such objects and their behavior (or lack thereof).
以上解析來(lái)自Wikipedia。
NullObject模式首次發(fā)表在“ 程序設(shè)計(jì)模式語(yǔ)言 ”系列叢書(shū)中。一般的,在面向?qū)ο笳Z(yǔ)言中,對(duì)對(duì)象的調(diào)用前需要使用判空檢查,來(lái)判斷這些對(duì)象是否為空,因?yàn)樵诳找蒙蠠o(wú)法調(diào)用所需方法。
空對(duì)象模式的一種典型實(shí)現(xiàn)方式如下圖所示(圖片來(lái)自網(wǎng)絡(luò)):

示例代碼如下(命名來(lái)自網(wǎng)絡(luò),哈哈到底是有多懶):
Nullable是空對(duì)象的相關(guān)操作接口,用于確定對(duì)象是否為空,因?yàn)樵诳諏?duì)象模式中,對(duì)象為空會(huì)被包裝成一個(gè)Object,成為Null Object,該對(duì)象會(huì)對(duì)原有對(duì)象的所有方法進(jìn)行空實(shí)現(xiàn)。。
public interface Nullable {
boolean isNull();
}
這個(gè)接口定義了業(yè)務(wù)對(duì)象的行為。
public interface DependencyBase extends Nullable {
void Operation();
}
這是該對(duì)象的真實(shí)類(lèi),實(shí)現(xiàn)了業(yè)務(wù)行為接口DependencyBase與空對(duì)象操作接口Nullable。
public class Dependency implements DependencyBase, Nullable {
@Override
public void Operation() {
System.out.print("Test!");
}
@Override
public boolean isNull() {
return false;
}
}
這是空對(duì)象,對(duì)原有對(duì)象的行為進(jìn)行了空實(shí)現(xiàn)。
public class NullObject implements DependencyBase{
@Override
public void Operation() {
// do nothing
}
@Override
public boolean isNull() {
return true;
}
}
在使用時(shí),可以通過(guò)工廠調(diào)用方式來(lái)進(jìn)行空對(duì)象的調(diào)用,也可以通過(guò)其他如反射的方式對(duì)對(duì)象進(jìn)行調(diào)用(一般多耗時(shí)幾毫秒)在此不進(jìn)行詳細(xì)敘述。
public class Factory {
public static DependencyBase get(Nullable dependencyBase){
if (dependencyBase == null){
return new NullObject();
}
return new Dependency();
}
}
這是一個(gè)使用范例,通過(guò)這種模式,我們不再需要進(jìn)行對(duì)象的判空操作,而是可以直接使用對(duì)象,也不必?fù)?dān)心NPE(NullPointerException)的問(wèn)題。
public class Client {
public void test(DependencyBase dependencyBase){
Factory.get(dependencyBase).Operation();
}
}
關(guān)于空對(duì)象模式,更具體的內(nèi)容大家也可以多找一找資料,上述只是對(duì)NullObject的簡(jiǎn)單介紹,但是,今天我要推薦的是一款協(xié)助判空的插件NR Null Object,讓我們來(lái)優(yōu)雅地進(jìn)行判空,不再進(jìn)行一頓操作來(lái)定義繁瑣的空對(duì)象接口與空獨(dú)享實(shí)現(xiàn)類(lèi)。
.NR Null Object
NR Null Object是一款適用于Android Studio、IntelliJ IDEA、PhpStorm、WebStorm、PyCharm、RubyMine、AppCode、CLion、GoLand、DataGrip等IDEA的Intellij插件。其可以根據(jù)現(xiàn)有對(duì)象,便捷快速生成其空對(duì)象模式需要的組成成分,其包含功能如下:
- 分析所選類(lèi)可聲明為接口的方法;
- 抽象出公有接口;
- 創(chuàng)建空對(duì)象,自動(dòng)實(shí)現(xiàn)公有接口;
- 對(duì)部分函數(shù)進(jìn)行可為空聲明;
- 可追加函數(shù)進(jìn)行再次生成;
- 自動(dòng)的函數(shù)命名規(guī)范
讓我們來(lái)看一個(gè)使用范例:

怎么樣,看起來(lái)是不是非常快速便捷,只需要在原有需要進(jìn)行多次判空的對(duì)象中,郵件彈出菜單,選擇Generate,并選擇NR Null Object即可自動(dòng)生成相應(yīng)的空對(duì)象組件。
那么如何來(lái)獲得這款插件呢?
安裝方式
可以直接通過(guò)IDEA的Preferences中的Plugins倉(cāng)庫(kù)進(jìn)行安裝。
選擇 Preferences → Plugins → Browse repositories

搜索“NR Null Oject”或者“Null Oject”進(jìn)行模糊查詢(xún),點(diǎn)擊右側(cè)的Install,restart IDEA即可。

總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
SpringMVC中使用bean來(lái)接收f(shuō)orm表單提交的參數(shù)時(shí)的注意點(diǎn)
本篇文章主要介紹了SpringMVC中使用bean來(lái)接收f(shuō)orm表單提交的參數(shù)時(shí)的注意點(diǎn),具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-05-05
mybatis Invalid bound statement(not foun
這篇文章主要介紹了mybatis Invalid bound statement(not found)排坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Java注解之超越Javadoc的元數(shù)據(jù)利器詳解
本文將深入探討 Java 注解的定義、類(lèi)型、內(nèi)置注解、自定義注解、保留策略、實(shí)際應(yīng)用場(chǎng)景及最佳實(shí)踐,無(wú)論是初學(xué)者還是資深開(kāi)發(fā)者,都能通過(guò)本文了解如何利用注解提升代碼質(zhì)量和開(kāi)發(fā)效率2025-05-05
Jackson中json格式的字符串與對(duì)象的互相轉(zhuǎn)換方式
這篇文章主要介紹了Jackson中json格式的字符串與對(duì)象的互相轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
關(guān)于@ConditionalOnProperty的作用及用法說(shuō)明
這篇文章主要介紹了關(guān)于@ConditionalOnProperty的作用及用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
SpringBoot加載外部依賴(lài)過(guò)程解析
這篇文章主要介紹了SpringBoot加載外部依賴(lài)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01

