java 返回空数组_避免在Java中检查Null语句
1.概述
通常,在Java代碼中處理null變量、引用和集合很棘手。它們不僅難以識別,而且處理起來也很復雜。事實上,在編譯時無法識別處理null的任何錯誤,會導致運行時NullPointerException。 在本教程中,我們將了解在Java中檢查null的必要性以及幫助我們避免在代碼中進行空檢查的各種替代方法。
2.什么是NullPointerException?
根據 Javadoc for NullPointerException,當應用程序在需要對象的情況下嘗試使用null時拋出它,例如:
- 調用null對象的實例方法
- 訪問或修改空對象的字段
- 取null的長度,就好像它是一個數組一樣
- 訪問或修改null的插槽,就像它是一個數組一樣
- 拋出null就好像它是一個Throwable值
讓我們快速查看導致此異常的Java代碼的幾個示例:
在這里,我們嘗試調用null引用的方法調用。這將導致NullPointerException。 另一個常見示例是,如果我們嘗試訪問空數組:
這會在第6行導致 NullPointerException。 因此,訪問空 對象的任何字段,方法或索引會導致 NullPointerException,如上面的示例所示。避免 NullPointerException的 常見方法是檢查 null:
在現實世界中,程序員發現很難識別哪些對象可以為 null。積極安全的策略可能是為每個對象檢查 null。但是,這會導致大量冗余空值檢查,并使我們的代碼可讀性降低。在接下來的幾節中,我們將介紹Java中的一些備選方案,以避免這種冗余。
3.通過API約定處理null
如上一節所述,訪問null對象的方法或變量會導致NullPointerException。 我們還討論了在訪問對象之前對對象進行空 檢查可以消除NullPointerException的可能性。 但是,通常有API可以處理空值。例如:
在 print()方法調用將只打印 null,但不會拋出異常。同樣, process()永遠不會在其響應中返回 null。它反而拋出異常。 因此對于訪問上述API的客戶端代碼,不需要進行空檢查。但是此類API必須在約定中明確說明。API發布此類約定的常見位置是JavaDoc。但是,這并未明確指出API約定,因此依賴于客戶端代碼開發人員來確保其合規性。 在下一節中,我們將看到一些IDE和其他開發工具如何幫助開發人員解決這個問題。
4.自動化API約定
4.1.使用靜態代碼分析
靜態代碼分析工具有助于提高代碼質量。一些這樣的工具也允許開發人員維護null約定(Null Contracts)。一個例子是 FindBugs。 FindBugs通過 @Nullable和 @NonNull注解幫助管理null約定。我們可以在任何方法,字段,局部變量或參數上使用這些注釋。這使得對客戶端代碼明確指出注釋類型是否為 null。我們來看一個例子:
在這里, @NonNull清楚地表明參數不能為 null。如果客戶端代碼在不檢查 null參數的情況下調用此方法 ,則 FindBugs將在編譯時生成警告。
4.2.使用靜態代碼分析
開發人員通常依靠IDE來編寫Java代碼。使用代碼自動補全和有用警告等功能,例如可能沒有聲明變量,在很大程度上對編碼有幫助。 一些IDE還允許開發人員管理API約定(API Contracts),從而消除對靜態代碼分析工具的需求。IntelliJ IDEA提供 @NonNull和 @Nullable注解。要在IntelliJ中添加對這些注釋的支持,我們必須添加以下Maven依賴項:
現在,如果沒有對 Null進行檢查,IntelliJ將生成警告,就像我們在上一個示例中一樣。 IntelliJ還提供了用于處理復雜API約束的Contract注釋。
5.斷言
到目前為止,我們只討論過從客戶端代碼中去除空檢查的必要性。但是,這很少適用于實際應用。現在,假設我們正在使用一個不能接受空參數的API,或者可以返回必須由客戶端處理的空響應。這表明我們需要檢查參數或空值的響應。 這里,我們可以使用Java Assertions代替傳統的 null檢查條件語句:
在第2行中,我們檢查null參數。如果啟用了斷言,則會導致 AssertionError。 盡管這是斷言非空參數等前置條件的好方法,但這種方法主要存在兩個問題:
- 1.通常在JVM中禁用斷言
- 2.一個虛假的聲明將導致在未經檢查的錯誤無法恢復
因此,建議程序員不要使用斷言來檢查條件。在以下部分中,我們將討論處理null檢查的其他方法
6.通過編碼實踐避免NULL檢查
6.1.前提條件
編寫早期失敗的代碼通常是一種很好的做法。因此,如果一個API不允許接受有多個參數為空,更好地方法是預先檢查API中的每一個非空參數。
例如,讓我們看看兩個方法:一個早期失敗,另一個不失敗:
顯然,我們應該更喜歡 goodAccept()而不是 badAccept()。 作為替代方案,我們也可以使用Guava的前置條件來驗證API參數。
6.2.使用原語而不是包裝類
由于 null對于像int這樣的原語來說不是一個可接受的值,我們應該盡可能優先于它們的包裝對象,如 Integer。 考慮一個對兩個整數求和的方法的兩個實現:
6.3.空集合
有時,我們需要將一個集合作為方法的響應返回。對于這樣的方法,我們應該總是嘗試返回一個空集合而不是 null
因此,我們在調用此方法時避免了客戶端執行空檢查的需要。
7.使用 Objects
Java 7引入了新的Objects API。此API有幾個靜態 實用程序方法,可以消除大量冗余代碼。讓我們看看一個這樣的方法, requireNonNull():
現在,讓我們測試 accept方法:
因此,如果將null 作為參數傳遞,則 accept()會拋出 NullPointerException。 此類還具有 isNull()和 nonNull()方法,可用作謂詞來檢查對象是否為null。
8.使用Optional
Java8在該語言中引入了一個新的 OptionalAPI。與null相比,這為處理可選值提供了更好的約定。讓我們看看 Optional如何消除對空檢查的需求:
通過返回一個 Optional,如上所示,該 process()方法使得明確告訴調用者,響應可能是Null,并且必須在編譯時處理。 這顯然消除了客戶端代碼中對空檢查的需求。可以使用 OptionalAPI的聲明性樣式以不同方式處理空響應:
此外,它還為API開發人員提供了一個更好的約定,以向客戶端表明API可以返回空響應。 雖然我們不需要對此API的調用者進行空檢查,但我們使用它來返回空響應。為避免這種情況, Optional提供了一個 ofNullable方法,該方法返回具有指定值的 Optional,如果值為 null,則返回 empty:
9.庫
9.1.使用Lombok
Lombok是一個很棒的庫,可以減少項目中樣板代碼的數量。它附帶了一組注釋,取代了我們經常在Java應用程序中編寫的代碼的常見部分,例如getter,setter和toString(),僅舉幾例。
另一個注釋是 @NonNull。 因此,如果項目已經使用Lombok來消除樣板代碼,則 @NonNull可以代替作為空檢查。
在繼續查看一些示例之前,添加一個Maven依賴項引入Lombok:
現在,我們可以在需要進行空檢查的地方 使用 @NonNull:
因此,我們只是注解了需要進行null檢查的對象,并且Lombok生成了已編譯的類:
如果 param為null,則此方法拋出 NullPointerException。該方法必須在其約定中明確說明,并且客戶端代碼必須處理異常。
9.2.使用StringUtils
一般來說,字符串驗證包括除空值檢查空值。因此,常見的驗證聲明是:
如果我們必須處理很多 String類型,這很快就會變得多余。這就是 StringUtils派上用場的地方。在我們看到這個動作之前,讓我們為commons-lang3添加一個Maven依賴項:
現在讓我們用 StringUtils重構上面的代碼 :
因此,我們使用靜態實用程序方法 isNotEmpty()替換了 null或空檢查。此API提供了其它強大而實用方法來處理常見的String函數。
10.結論
在本文中,我們研究了發生 NullPointerException的各種原因以及難以識別的原因。然后,我們使用了各種方法來避免代碼中的冗余,以及對使用參數,返回類型和其他變量進行空檢查。
轉載自公眾號:鍋外的大佬
總結
以上是生活随笔為你收集整理的java 返回空数组_避免在Java中检查Null语句的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python定义类object_Pyth
- 下一篇: cesium 3dtiles 加载本地数