日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Objects.requireNonNull 方法说明

發(fā)布時間:2025/3/12 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Objects.requireNonNull 方法说明 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在寫代碼的時候,Idea經(jīng)常會提醒我們可以使用這個方法來進(jìn)行參數(shù)非空檢查, 這個方法的源碼也非常簡單, 如下所示:

/*** Checks that the specified object reference is not {@code null}. This* method is designed primarily for doing parameter validation in methods* and constructors, as demonstrated below:* <blockquote><pre>* public Foo(Bar bar) {* this.bar = Objects.requireNonNull(bar);* }* </pre></blockquote>** @param obj the object reference to check for nullity* @param <T> the type of the reference* @return {@code obj} if not {@code null}* @throws NullPointerException if {@code obj} is {@code null}*/ public static <T> T requireNonNull(T obj) {if (obj == null)throw new NullPointerException();return obj; }

這個方法是 Objects 類的一個靜態(tài)方法, Objects 類是一個 Java 靜態(tài)類, 里面包含了很多 Java 工具方法, 其方法都是靜態(tài)方法, 其類的說明文檔如下:

/*** This class consists of {@code static} utility methods for operating* on objects. These utilities include {@code null}-safe or {@code* null}-tolerant methods for computing the hash code of an object,* returning a string for an object, and comparing two objects.** @since 1.7*/ public final class Objects {... }

可以看出, 這個類還包括了很多關(guān)于類操作的使用工具方法, 例如比較兩個類是否相等, 計算類的 Hash Code 等方法, 這個類以后有機(jī)會進(jìn)行學(xué)習(xí)和介紹.

回到 requireNonNull() 這個方法, 其源碼實現(xiàn)非常簡單, 只是進(jìn)行了一個簡單的判斷, 如果所要判斷的元素為 null, 則返回空指針異常 NullPointerException, 否則直接返回對應(yīng)的對象.

這看上去好像是一個多余的操作, 因為如果我們試圖去調(diào)用一個空對象的方法, 也會拋出 NullPointerException 運行時異常, 那么我們?yōu)槭裁匆啻艘慌e進(jìn)行這樣的一次檢查呢? 這一問題在 StackOverflow 上有人進(jìn)行了解答 Why should one use Objects.requireNonNull?.

看了他們的回答, 總結(jié)為以下幾點:

首先, 從這個方法的名稱可以看出, 這個方法使用的場景是, 我們使用一個對象的方法時, 正常的運行狀態(tài)應(yīng)該能保證這個對象的引用非空, 如果這個對象為空了, 那一定是其他某個地方出錯了, 所以我們應(yīng)該拋出一個異常, 我們不應(yīng)該在這里處理這個非空異常.

其次, 這里涉及到一個很重要的編程思想, 就是 Fail-fast 思想, 翻譯過來就是, 讓錯誤盡可能早的出現(xiàn), 不要等到我們很多工作執(zhí)行到一半之后才拋出異常, 這樣很可能使得一部分變量處于異常狀態(tài), 出現(xiàn)更多的錯誤. 這也是 requireNonNull 這個方法的設(shè)計思想, 讓錯誤盡早出現(xiàn). 使用這個方法, 我們明確的拋出異常, 發(fā)生錯誤時, 我們立刻拋出異常.

StackOverflow 中的一個回答舉了一個具體的例子來回答這個問題, 例如有下面這樣一個類:

public class Dictionary {private final List<String> words;private final LookupService lookupService;public Dictionary(List<String> words) {this.words = this.words;this.lookupService = new LookupService(words);}public boolean isFirstElement(String userData) {return lookupService.isFirstElement(userData);} }public class LookupService {List<String> words;public LookupService(List<String> words) {this.words = words;}public boolean isFirstElement(String userData) {return words.get(0).contains(userData);} }

這里, 兩個類是包含的關(guān)系, 傳入的 List 參數(shù)沒有做非空檢查. 如果我們一不小心在 Dictionary 的構(gòu)造方法中傳入了 null, 如下所示:

Dictionary dictionary = new Dictionary(null); // exception thrown lately : only in the next statement boolean isFirstElement = dictionary.isFirstElement("anyThing");

我們在構(gòu)造時沒有任何異常, 但是當(dāng)我們調(diào)用方法時, 會拋出 NPE:

Exception in thread "main" java.lang.NullPointerExceptionat LookupService.isFirstElement(LookupService.java:5)at Dictionary.isFirstElement(Dictionary.java:15)at Dictionary.main(Dictionary.java:22)

JVM 告訴我們, 在執(zhí)行 return words.get(0).contains(userData) 這條語句時, 發(fā)生了異常, 但是這個異常非常不明確, 從報錯信息來看, 有多種可能會導(dǎo)致這個異常發(fā)生, 是因為 words 為空, 還是 words.get(0) 為空? 或者兩者都為空? 這都是不明確的. 同時, 我們也無法確定是在這兩個類的哪個環(huán)節(jié)出了錯, 這些都是不明確的, 給我們程序 debug 造成了很大的困難.

然而, 當(dāng)我們使用如下方式實現(xiàn):

public Dictionary(List<String> words) {this.words = Objects.requireNonNull(words);this.lookupService = new LookupService(words); }

按照這種實現(xiàn)方式, 在我們執(zhí)行構(gòu)造方法時, 就會明確拋出錯誤.

// exception thrown early : in the constructor Dictionary dictionary = new Dictionary(null);// we never arrive here boolean isFirstElement = dictionary.isFirstElement("anyThing"); Exception in thread "main" java.lang.NullPointerExceptionat java.util.Objects.requireNonNull(Objects.java:203)at com.Dictionary.(Dictionary.java:15)at com.Dictionary.main(Dictionary.java:24)

這樣我們進(jìn)行 debug 時就明確很多, 少走很多彎路.

除此之外, 這個方法的作用也是一個明確和不明確的區(qū)別, 使用這個方法表示我們明確進(jìn)行了這個判斷, 其實與我們自己使用 if-else 進(jìn)行判斷是一樣的, 只是這個工具類簡化了這樣的操作, 讓我們的代碼看上去更加簡潔, 可讀性更強(qiáng).

此外, requireNonNull 方法有一個重載方法, 可以提供一個報錯信息, 以供我們 debug 的時候顯示. 我們使用這個引用的時候, 應(yīng)當(dāng)保證非空, 如果不然, 會拋出異常告訴我們其他地方出錯了, 這里出現(xiàn)了空指針異常. 這個方法重載的實現(xiàn)如下:

/*** Checks that the specified object reference is not {@code null} and* throws a customized {@link NullPointerException} if it is. This method* is designed primarily for doing parameter validation in methods and* constructors with multiple parameters, as demonstrated below:* <blockquote><pre>* public Foo(Bar bar, Baz baz) {* this.bar = Objects.requireNonNull(bar, "bar must not be null");* this.baz = Objects.requireNonNull(baz, "baz must not be null");* }* </pre></blockquote>** @param obj the object reference to check for nullity* @param message detail message to be used in the event that a {@code* NullPointerException} is thrown* @param <T> the type of the reference* @return {@code obj} if not {@code null}* @throws NullPointerException if {@code obj} is {@code null}*/ public static <T> T requireNonNull(T obj, String message) {if (obj == null)throw new NullPointerException(message);return obj; }

例如, 我們在 Android 中可以按照如下方式使用:

String username = Objects.requireNonNull(textInputLayoutUsername.getEditText(), "TextInputLayout must have an EditText as child").getText().toString();

這是一個從 TextInpuLayout 獲取用戶輸入內(nèi)容的方法, 通常使用 TextInputLayout 包裹一個 EditText 來接收用戶輸入, 因此我們需要通過 TextInputLayout 的 getEditText() 方法來獲取對應(yīng)的 EditText, 如果我們布局有問題, 則該方法可能返回 null, 因此我們可以通過上述方法, 拋出一個明確異常, 如果運行時出現(xiàn)問題, 我們也可以很快知道是因為我們 TextInputLayout 無法獲取 EditText 而出錯的.

總結(jié)

以上是生活随笔為你收集整理的Objects.requireNonNull 方法说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。