簡體   English   中英

檢查 Java 中的 null 值的最佳方法是什么?

[英]Best way to check for null values in Java?

在調用 object 的 function 之前,我需要檢查 object 是否為NullPointerException

go 關於這個的最佳方法是什么? 我考慮過這些方法。
Java的最佳編程實踐是哪一個?

// Method 1
if (foo != null) {
    if (foo.bar()) {
        etc...
    }
}

// Method 2
if (foo != null ? foo.bar() : false) {
    etc...
}

// Method 3
try {
    if (foo.bar()) {
        etc...
    }
} catch (NullPointerException e) {
}

// Method 4 -- Would this work, or would it still call foo.bar()?
if (foo != null && foo.bar()) {
    etc...
}

方法4最好。

if(foo != null && foo.bar()) {
   someStuff();
}

將使用短路評估,這意味着如果logical AND的第一個條件為假,則結束。

最后一個也是最好的。 邏輯與

  if (foo != null && foo.bar()) {
    etc...
}

因為在邏輯&&

沒有必要知道右手邊是什么,結果一定是假的

喜歡閱讀: Java邏輯運算符短路

在Java 8中,檢查null的最佳方法是:

Objects.isNull(obj) //returns true if the object is null

Objects.nonNull(obj) //returns true if object is not-null

if(Objects.nonNull(foo) && foo.something()) // Uses short-circuit as well. No Null-pointer Exceptions are thrown.

除此之外......您還可以選擇Guava的Optional Class

減少類似於(obj=null)的類型錯誤,它總是返回true如前面的答案所述。

  • 不要捕獲NullPointerException 這是一種不好的做法。 最好確保該值不為空。
  • 方法#4 對你有用。 它不會評估第二個條件,因為 Java 有短路(即,如果后續條件不改變布爾表達式的最終結果,則不會評估它們)。 在這種情況下,如果邏輯 AND 的第一個表達式計算結果為 false,則不需要計算后續表達式。

方法 4 無疑是最好的,因為它清楚地表明會發生什么並且使用最少的代碼。

方法 3 在各個層面上都是錯誤的。 您知道該項目可能為空,因此這不是特殊情況,您應該檢查一下。

方法 2 只是使它比需要的更復雜。

方法 1 只是方法 4,多了一行代碼。

Java 7 中,您可以使用Objects.requireNonNull() java.util添加Objects類的導入。

public class FooClass {
    //...
    public void acceptFoo(Foo obj) {
        //If obj is null, NPE is thrown
        Objects.requireNonNull(obj).bar(); //or better requireNonNull(obj, "obj is null");
    }
    //...
}

我會說方法 4 是我看過的代碼中最通用的習慣用法。 但這對我來說總是有點臭。 它假定 foo == null 與 foo.bar() == false 相同。

這對我來說並不總是正確的。

方法 4 是我的首選方法。 && 運算符的短路使代碼最具可讀性。 方法 3,Catching NullPointerException,在大多數情況下是不贊成的,因為簡單的 null 檢查就足夠了。

如果你控制被調用的 API,可以考慮使用Guava 的 Optional 類

更多信息在這里 更改您的方法以返回Optional<Boolean>而不是Boolean

通過調用Optional一種方便的方法,這會通知調用代碼它必須考慮 null 的可能性

正如其他人所說,#4 是不使用庫方法時的最佳方法。 但是,您應該始終將 null 放在比較的左側,以確保在出現拼寫錯誤時不會意外地將 null 分配給 foo。 在這種情況下,編譯器會發現錯誤。

// You meant to do this
if(foo != null){

// But you made a typo like this which will always evaluate to true
if(foo = null)

// Do the comparison in this way
if(null != foo)

// So if you make the mistake in this way the compiler will catch it
if(null = foo){

// obviously the typo is less obvious when doing an equality comparison but it's a good habit either way
if(foo == null){
if(foo =  null){

您還可以使用StringUtils.isNoneEmpty("")來檢查是否為 null 或為空。

如果你打算用雙等號“==”檢查,那么用對象引用檢查 null 就像

if(null == obj) 

代替

if(obj == null)

因為如果你輸入錯誤 single equal if(obj = null) 它將返回 true (分配對象返回成功(其值為 'true' )。

如果您無權訪問 commons apache 庫,則以下內容可能會正常工作

if(null != foo && foo.bar()) {
//do something
}

你最后的提議是最好的。

if (foo != null && foo.bar()) {
    etc...
}

因為:

  1. 閱讀起來更容易。
  2. 這是安全的:如果 foo == null,則永遠不會執行 foo.bar()。
  3. 它可以防止不良做法,例如捕獲 NullPointerExceptions(大部分時間是由於代碼中的錯誤)
  4. 它的執行速度應該與其他方法一樣快甚至更快(盡管我認為幾乎不可能注意到它)。

我們可以使用 Object 類的 Object.requireNonNull 靜態方法。 實現如下

public void someMethod(SomeClass obj) {
    Objects.requireNonNull(obj, "Validation error, obj cannot be null");
}

簡單的一行代碼來檢查 null :

namVar == null ? codTdoForNul() : codTdoForFul();

對於 java 11+,您可以使用Objects.nonNull(Object obj)

if(nonNull(foo)){ 
//
}
public <T, U> U defaultGet(T supplier, Function<T, U> mapper, U defaultValue) {
        return Optional.ofNullable(supplier).map(mapper).orElse(defaultValue);

    }

如果您喜歡函數編程,可以創建此函數

Java中處理空值的通用方法

  1. 如果該對象不為空,我們將執行以下操作。

    一種。 我們可以改變對象(I)

    我們可以返回 something(O) 作為輸出而不是改變對象 (I)

    C。 我們可以同時做

在這種情況下,我們需要傳遞一個函數,該函數需要接受作為我們對象的輸入 param(I) 如果我們這樣接受,那么我們可以根據需要改變該對象。 而且該功能可能是(O)。

  1. 如果 object 為 null 那么我們將做以下事情

    一種。 我們可能會以自定義的方式拋出異常

    我們可能會返回一些東西。

在這種情況下,對象為 null,因此我們需要提供該值,否則我們可能需要拋出異常。

我舉兩個例子。

  1. 如果我想在字符串中執行修剪,那么該字符串不應為空。 在這種情況下,我們必須額外檢查空值,否則我們會得到 NullPointerException
public String trimValue(String s){
   return s == null ? null : s.trim();
}
  1. 如果該對象不為空,我想為對象設置一個新值的另一個函數,否則我想拋出一個運行時異常。
public void setTeacherAge(Teacher teacher, int age){
   if (teacher != null){
      teacher.setAge(age);
   } else{
      throw new RuntimeException("teacher is null")
    }
}

在我的解釋中,我創建了一個接受值(值可能為空)的通用方法,一個在對象不為空時將執行的函數,以及在對象為空時將執行的另一個供應商函數。

泛型函數

  public <I, O> O setNullCheckExecutor(I value, Function<I, O> nonNullExecutor, Supplier<O> nullExecutor) {
        return value != null ? nonNullExecutor.apply(value) : nullExecutor.get();
    }

所以有了這個通用函數后,我們可以對示例方法1進行如下操作。

//To Trim a value
        String trimmedValue = setNullCheckExecutor(value, String::trim, () -> null);

這里, nonNullExecutor 函數是修剪值(使用方法參考)。 nullExecutorFunction 將返回 null,因為它是一個標識函數。

2.

// mutate the object if not null otherwise throw a custom message runtime exception instead of NullPointerException
 setNullCheckExecutor(teacher, teacher -> {
            teacher.setAge(19);
            return null;
        }, () -> {
            throw new RuntimeException("Teacher is null");
        });

在處理 function 時,我經常尋找 null -

public static void doSomething(Object nullOrNestedObject) {
     if (nullOrNestedObject == null || nullOrNestedObject.getNestedObject()) {
        log.warn("Invalid argument !" );
        return;
        // Or throw an exception
        // throw new IllegalArgumentException("Invalid argument!");

     }
    nullOrNestedObject.getNestedObject().process()
     ... // Do other function stuff
}

這樣,如果它是 null 它只會提前停止執行,並且您不必將所有邏輯嵌套在 if 中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM