88

オブジェクトの関数を呼び出す前に、オブジェクトが null かどうかを確認して、NullPointerException.

これについて最善の方法は何ですか?これらの方法を検討しました。
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

18 に答える 18

122

方法 4 が最適です。

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

短絡評価を使用します。つまり、 a の最初の条件logical ANDが falseの場合に終了します。

于 2013-06-25T16:11:38.030 に答える
16

最後で最高のもの。つまり 、論理積

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

なぜなら論理的に&&

右辺が何であるかを知る必要はありません。結果は false でなければなりません

読むことを好む:Java論理演算子の短絡

于 2013-06-25T16:10:19.250 に答える
5
  • キャッチしないでくださいNullPointerException。それは悪い習慣です。値が null でないことを確認することをお勧めします。
  • 方法 4 が有効です。Java には短絡があるため、2 番目の条件は評価されません (つまり、ブール式の最終結果が変更されない場合、後続の条件は評価されません)。この場合、論理 AND の最初の式が false と評価された場合、後続の式を評価する必要はありません。
于 2013-06-25T16:12:37.097 に答える
5

方法 4 は、何が起こるかを明確に示し、最小限のコードを使用するため、はるかに優れています。

方法 3 はすべてのレベルで間違っています。アイテムが null である可能性があることはわかっているため、例外的な状況ではなく、チェックする必要があります。

方法 2 は、必要以上に複雑にしているだけです。

方法 1 は、コード行を追加した方法 4 です。

于 2013-06-25T16:13:43.577 に答える
4

Java 7では、 を使用できますObjects.requireNonNull()Objectsからのクラスのインポートを追加しjava.utilます。

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");
    }
    //...
}
于 2015-03-10T05:08:34.377 に答える
2

方法 4 は、私が見たコードからの最も一般的なイディオムだと思います。しかし、これはいつも私には少し臭いです。foo == null は foo.bar() == false と同じであると想定しています。

それはいつも私にとって正しいとは限りません。

于 2013-06-25T16:13:10.850 に答える
2

方法 4 は、私の好みの方法です。&& 演算子の短絡により、コードが最も読みやすくなります。方法 3 の NullPointerException のキャッチは、ほとんどの場合、単純な null チェックで十分な場合に嫌われます。

于 2013-06-25T16:13:19.817 に答える
1

アップデート

Java 開発者がこの NullPointerException Hell をコードから削除するための Java ライブラリ (Maven Dependency) を作成しました。私のリポジトリをチェックしてください。

NullUtil リポジトリ

Java で Null 値を処理する汎用メソッド

<script src="https://gist.github.com/rcvaram/f1a1b89193baa1de39121386d5f865bc.js"></script>

  1. そのオブジェクトが null でない場合、次のことを行います。

    を。オブジェクトを変異させることができます (I)

    b. オブジェクト (I) を変更する代わりに、何か (O) を出力として返すことができます。

    c. 私たちは両方を行うことができます

この場合、オブジェクトである入力 param(I) を取得する必要がある関数を渡す必要があります。そのように取得すると、必要に応じてそのオブジェクトを変更できます。また、その関数は何か (O) である可能性があります。

  1. オブジェクトが null の場合、次のことを行います

    を。カスタマイズされた方法で例外をスローする場合があります

    b. 何かを返すかもしれません。

この場合、オブジェクトは null であるため、値を提供する必要があるか、例外をスローする必要がある場合があります。

2つの例を挙げます。

  1. String でトリムを実行する場合、その文字列は null であってはなりません。その場合、null 値を追加でチェックする必要があります。そうしないと、NullPointerException が発生します。
public String trimValue(String s){
   return s == null ? null : s.trim();
}
  1. そのオブジェクトがnullでない場合、オブジェクトに新しい値を設定したい別の関数。それ以外の場合は、ランタイム例外をスローします。
public void setTeacherAge(Teacher teacher, int age){
   if (teacher != null){
      teacher.setAge(age);
   } else{
      throw new RuntimeException("teacher is null")
    }
}

私の説明では、値 (値は null の場合もあります) を取る汎用メソッド、オブジェクトが null でない場合に実行される関数、およびオブジェクトが 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 Function が値をトリムします (メソッド リファレンスが使用されます)。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");
        });
于 2021-12-02T14:08:00.037 に答える
1

StringUtils.isNoneEmpty("")また、check is null または empty にも使用できます。

于 2017-08-09T11:26:04.720 に答える
0

あなたの最後の提案は最高です。

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

なぜなら:

  1. 読みやすくなっています。
  2. 安全です: foo == null の場合、foo.bar() は決して実行されません。
  3. NullPointerExceptions をキャッチするなどの悪い習慣を防ぎます (ほとんどの場合、コードのバグが原因です)。
  4. 他の方法と同じかそれ以上の速度で実行されるはずです (私はそれに気付くことはほとんど不可能だと思いますが)。
于 2013-06-25T16:30:56.773 に答える
0

commons apache ライブラリにアクセスできない場合は、次の方法で問題なく動作する可能性があります。

if(null != foo && foo.bar()) {
//do something
}
于 2013-06-25T16:15:47.217 に答える