如何在 Java8 中風(fēng)騷走位避開空指針異常

要說 Java 編程中哪個異常是你印象最深刻的,那 NullPointerException 空指針可以說是臭名昭著的考阱。不要說初級程序員會碰到翠忠, 即使是中級,專家級程序員稍不留神乞榨,就會掉入這個坑里秽之。

Null 引用的發(fā)明者 Tony Hoare 曾在 2009 年作出道歉聲明,聲明中表示吃既,到目前為止考榨,空指針異常大約給企業(yè)已造成數(shù)十億美元的損失。

下面是 Tony Hoare 的原話:

我將 Null 引用的設(shè)計(jì)稱為是一個數(shù)十億美元的錯誤鹦倚。1965 那年河质,我正在用面向?qū)ο笳Z言(ALGOL W) 設(shè)計(jì)首個功能全面的系統(tǒng)。當(dāng)時我的考量是震叙,確保所有被使用的引用都是安全的掀鹅,編譯器會自動進(jìn)行檢查。但是媒楼,我沒有抵住誘惑乐尊,加入了 Null 引用,僅僅是為了實(shí)現(xiàn)起來省事划址。這之后科吭,它導(dǎo)致了數(shù)不清的 bug昏滴、錯誤和系統(tǒng)崩潰猴鲫,也為企業(yè)導(dǎo)致了不可估量的損失对人。

事已至此,我們必須學(xué)會面對它拂共。So, 我們要如何防止空指針異常呢牺弄?

唯一的辦法就是對可能為 Null 的對象添加檢查。但是 Null 檢查是繁瑣且痛苦的宜狐。所以一些比較新的語言為了處理 Null 檢查势告,特意添加了特殊的語法,如空合并運(yùn)算符抚恒。

在 Groovy 或 Kotlin 這樣的語言中也被稱為 Elvis 運(yùn)算符咱台。

不幸的是,在老版本的 Java 中并沒有提供這樣的語法糖俭驮。Java8 中在這方面做了改進(jìn)回溺。所以,這篇文章就特意來介紹一下如何在 Java8 中利用新特性來編寫防止 NullPointerException的發(fā)生混萝。

Java8 中如何加強(qiáng)對 Null 對象的檢查遗遵?

在業(yè)務(wù)系統(tǒng)中,對象中嵌套對象是經(jīng)常發(fā)生的場景逸嘀,如下示例代碼:

// 最外層對象

class Outer {

Nested nested;

Nested getNested() {

return nested;

}

}

// 第二層對象

class Nested {

Inner inner;

Inner getInner() {

return inner;

}

}

// 最底層對象

class Inner {

String foo;

String getFoo() {

return foo;

}

}

業(yè)務(wù)中车要,假設(shè)我們需要獲取 Outer 對象對底層的 Inner 中的 foo 屬性,我們必須寫一堆的非空校驗(yàn)崭倘,來防止發(fā)生 NullPointerException:

// 繁瑣的代碼

Outer outer = new Outer();

if (outer != null && outer.nested != null && outer.nested.inner != null) {

System.out.println(outer.nested.inner.foo);

}

通過 Optional

在 Java8 中翼岁,我們有更優(yōu)雅的解決方式,那就是使用 Optional是說司光,我們可以在一行代碼中琅坡,進(jìn)行流水式的 map 操作。而 map 方法內(nèi)部會自動進(jìn)行空校驗(yàn):

Optional.of(new Outer())

.map(Outer::getNested)

.map(Nested::getInner)

.map(Inner::getFoo

.ifPresent(System.out::println); // 如果不為空飘庄,最終輸出 foo 的值

通過 suppiler 函數(shù)自定義增強(qiáng) API

上面這種方式個人感覺還是有點(diǎn)啰嗦脑蠕,我們可以利用 suppiler 函數(shù)來出一個終極解決方案:

public static Optional resolve(Supplier resolver) {

try {

T result = resolver.get();

return Optional.ofNullable(result);

}

catch (NullPointerException e) {

// 可能會拋出空指針異常,直接返回一個空的 Optional 對象

return Optional.empty();

}

}

利用上面的 resolve 方法來重構(gòu)上述的非空校驗(yàn)代碼段:

Outer obj = new Outer();

// 直接調(diào)用 resolve 方法跪削,內(nèi)部做空指針的處理

resolve(() -> obj.getNested().getInner().getFoo());

.ifPresent(System.out::println); // 如果不為空谴仙,最終輸出 foo 的值

總結(jié)

你需要知道的是,上面這兩個解決方案并沒傳統(tǒng)的 null 檢查性能那么高效碾盐。但在絕大部分業(yè)務(wù)場景下晃跺,舍棄那么一丟丟的性能來方便編碼,是完全可取毫玖, 除非是那種對性能有嚴(yán)格要求的場景掀虎,我們才不建議使用凌盯。

個人覺得,真要拿這點(diǎn)性能說事烹玉,還不如去優(yōu)化優(yōu)化 sql 語句驰怎,業(yè)務(wù)邏輯等

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市二打,隨后出現(xiàn)的幾起案子县忌,更是在濱河造成了極大的恐慌,老刑警劉巖继效,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件症杏,死亡現(xiàn)場離奇詭異,居然都是意外死亡瑞信,警方通過查閱死者的電腦和手機(jī)厉颤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凡简,“玉大人逼友,你說我怎么就攤上這事∨琐辏” “怎么了翁逞?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長溉仑。 經(jīng)常有香客問我挖函,道長,這世上最難降的妖魔是什么浊竟? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任怨喘,我火速辦了婚禮,結(jié)果婚禮上振定,老公的妹妹穿的比我還像新娘必怜。我一直安慰自己,他們只是感情好后频,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布梳庆。 她就那樣靜靜地躺著,像睡著了一般卑惜。 火紅的嫁衣襯著肌膚如雪膏执。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天露久,我揣著相機(jī)與錄音更米,去河邊找鬼。 笑死毫痕,一個胖子當(dāng)著我的面吹牛征峦,可吹牛的內(nèi)容都是我干的迟几。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼栏笆,長吁一口氣:“原來是場噩夢啊……” “哼类腮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起竖伯,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤存哲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后七婴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡察滑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年打厘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贺辰。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡户盯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饲化,到底是詐尸還是另有隱情莽鸭,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布吃靠,位于F島的核電站硫眨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏巢块。R本人自食惡果不足惜礁阁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望族奢。 院中可真熱鬧姥闭,春花似錦、人聲如沸越走。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽廊敌。三九已至铜跑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間庭敦,已是汗流浹背疼进。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秧廉,地道東北人伞广。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓拣帽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嚼锄。 傳聞我的和親對象是個殘疾皇子减拭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容