日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
細說Java中的空指針異常

“只有客戶發(fā)展了,才有我們的生存與發(fā)展!”這是成都創(chuàng)新互聯(lián)公司的服務宗旨!把網(wǎng)站當作互聯(lián)網(wǎng)產(chǎn)品,產(chǎn)品思維更注重全局思維、需求分析和迭代思維,在網(wǎng)站建設中就是為了建設一個不僅審美在線,而且實用性極高的網(wǎng)站。創(chuàng)新互聯(lián)對網(wǎng)站制作、成都網(wǎng)站制作、網(wǎng)站制作、網(wǎng)站開發(fā)、網(wǎng)頁設計、網(wǎng)站優(yōu)化、網(wǎng)絡推廣、探索永無止境。

空引用破壞了Java類型安全性

Java通過提供??編譯類型的安全性??(Compile Type Safety),來保證開發(fā)人員不會錯配不同的變量類型。在下面的示例中,我們試圖將整形(Integer)值分配給某個字符串(String)變量,而Java會及時提醒您。

Java雖然會在編譯過程中,去驗證變量和賦值的類型,但是由于空值(NULL)代表了所有未初始化的對象,因此空值可以被分配為任何類型(如下圖所示),且Java不會報錯。

例如,Java允許如下賦值情況的出現(xiàn):

這些對象在未被初始化的情況下,就指向了空引用,往往會產(chǎn)生Java類型的安全性漏洞。如下代碼段所示,就Java而言,Null和真實對象可能并沒有什么區(qū)別,但是它會導致一些不可實現(xiàn)的操作:

同時,由于Null屬于String類型,因此在編譯如下代碼段時,Java甚至都不會有任何警告。

但是,我們一旦運行該程序代碼,就會出現(xiàn)失敗,并且會被提示如下的空指針異常:

空指針異常的定義

空指針異常屬于運行時的異常。當Java嘗試去調(diào)用真實對象上的任何方法時,如果在運行時中,該對象調(diào)用的是空引用(Null Reference),那么就會拋出異常。您可以通過鏈接--https://dzone.com/articles/java-exceptions-1,找到有關(guān)異常、及其根源的更多詳細信息。

由于種種原因,開發(fā)人員時常會忘記初始化對象和驗證對象。這往往是導致空指針異常的根源。下面讓我們根據(jù)上述例子,討論如何修復NPE。

解釋空指針異常

下面是一個帶有Address字段的User對象。它們都可能為空。

使用Simple != Null Check避免空指針異常

下面是通過簡單的檢查(并非Null Check),來防止該問題的發(fā)生:

作為改進方案,我們可以使用Optional,并通過map函數(shù),編寫出如下類似于前例的等效語句:

與簡單的Null Check相比,Optional能夠再次確保我們在ifPresent lambda中使用的數(shù)據(jù)不為空。這里的再次是指:如果User或Address的確為空的話,而且ifPresent被忽略了的話,即使我們忘記了使用Optional的相關(guān)功能,它也會以突出顯示.get()的方式,并提醒我們?yōu)樵O計提供Null Check。

其實,早在2014年,Optional就作為可選特性,在Java 1.8中被發(fā)布了。不過由于如下原因,導致其至今未能被廣泛地使用:

  • 由于Java本身非常冗長,因此Optional也跟著變得冗長起來,因此容易影響到代碼的整體質(zhì)量。
  • 對于各種map/flatmap/ifpresent邏輯,開發(fā)人員更傾向使用簡單明了的Null Check。
  • Optional本身可能會導致開發(fā)人員創(chuàng)建更多NPE,例如使用到Optional.of(nullable)。

因此,鑒于上述原因,一些開發(fā)團隊會更喜歡使用Null Check,并且會用一堆邏輯性的測試覆蓋率,來避免潛在的NPE。

Null Check和Optional真的能夠解決問題嗎?

雖然上面討論到的Null Check與Optional的使用目的都是針對空值數(shù)據(jù)進行驗證。其中,Optional還可以提醒開發(fā)者返回值為空。但是,它們無法解決隱藏在開發(fā)者頭腦中的關(guān)鍵問題——在編譯步驟中出現(xiàn)的疏忽與遺漏。

@NotNull@Nullable注釋處理器有助于識別潛在的空值

因此,我們需要一個解決方案,可以在編譯步驟中讀取代碼,并通知開發(fā)人員他們可能疏漏的潛在NPE場景。對此,我們可以使用具有豐富功能的Java注釋處理器(Annotation Processors)。您可以通過鏈接--https://www.javacodegeeks.com/2015/09/java-annotation-processors.html,了解如何使用注釋處理器,來檢查可變性的示例。

目前,業(yè)界有幾種與NPE問題相關(guān)的注釋處理器。它們并非遵循完全相同的方法。下面我們將重點討論@NotNull和@Nullable兩種注釋提供工具。

Lombok的@NotNull注釋

Lombok(譯者注:一種Java庫,提供了一組非常實用的注釋)的@NotNull注釋可用于生成那些僅在運行時(Runtime)阻斷執(zhí)行的非Null Check。下面的代碼段展示了該注釋、及其等效語句。

檢查器框架的@NonNull和@Nullable注釋處理器

??檢查器框架??(Checker Framework)提供了@NonNull和@Nullable注釋,以及可以識別潛在Null Check的編譯處理器的步驟。該框架可以通過強制開發(fā)人員指定的Nullability,來發(fā)現(xiàn)潛在的空值。因此,您的代碼必須明確聲明可返回的結(jié)果為Nullable或NotNullable。下面讓我們來看一個可能返回Null,而非String的簡單方法:

現(xiàn)在,讓我們使用檢查器框架,來檢驗是否可以完成編譯。

如您所見,它報出了錯誤,并且返回了一個未使用@Nullable注釋標記的疑似空字符串。那么,讓我們將其標記為@Nullable試試:

如果我們再次運行編譯檢查,則會得到如下錯誤信息:

可見,檢查器框架在第19行發(fā)現(xiàn)了一個潛在問題,即:我們在Nullable字符串上調(diào)用了.length()。下面,讓我們使用Null Check和Optional的ifPresent來予以修復:

在編譯之后,我們將得到如下成功的構(gòu)建信息:

檢查器框架的限制

至此,檢查器框架向我們展示了良好的檢查結(jié)果,并且突出了潛在的NPE。不過,其代價是我們必須通過@Nullable方法,標記所有可能為空的方法。為了突破該強制性的限制,我們可以創(chuàng)建一個帶有兩個字段的簡單類,并且將其中一個字段標記為@NonNull:

下面是經(jīng)由檢查器框架的檢查結(jié)果:

顯然,檢查器框架會強制要求我們構(gòu)造一個初始化id值的構(gòu)造函數(shù),例如:

可見,檢查器框架不僅能夠識別潛在的NPE,而且還會迫使我們遵循特定的設計要求。這在某種程度上犧牲了框架開發(fā)的靈活性。如果您對該問題有興趣的話,可以通過如下命令克隆我為您準備的示例:

git clone https://github.com/isicju/checker_framework_example


若要運行檢查器框架的話,請使用如下命令:

Mvn clean compile


檢查器框架的替代方案:Intellij Idea @NotNull注釋

當然,檢查器框架并非唯一的解決方案,Intellij Idea也提供了自己的注釋--@NotNull和@Nullable,并嵌入到了IDE的插件中。目前,我尚未找到在maven編譯步驟中添加它的方法。如果您對此有經(jīng)驗的話,歡迎您追加評論。

小結(jié)

通過上述討論,我們可以看到,避免空指針異常的方法可以總結(jié)為:

  • 首選使用Optional,而不是傳遞Null
  • 使用檢查器框架

當然,檢查器框架會給您的開發(fā)帶來一些限制。在實踐中,如果您必須避免使用Lombok、甚至是Builder Pattern(建造者模式)的話,我建議您基于生產(chǎn)環(huán)境的穩(wěn)定性考慮,去使用檢查器框架。

譯者介紹

陳 峻 (Julian Chen),社區(qū)編輯,具有十多年的IT項目實施經(jīng)驗,善于對內(nèi)外部資源與風險實施管控,專注傳播網(wǎng)絡與信息安全知識與經(jīng)驗;持續(xù)以博文、專題和譯文等形式,分享前沿技術(shù)與新知;經(jīng)常以線上、線下等方式,開展信息安全類培訓與授課。

【原標題】Null Pointer Exception in Java: Causes and Ways to Avoid It(作者:Dmitry Egorov)


新聞標題:細說Java中的空指針異常
網(wǎng)頁鏈接:http://www.dlmjj.cn/article/cdhdhjg.html