7

オブジェクトがnull でないかどうかをチェックするときに、 NullPointerException の代わりに IllegalArgumentException をスローするApache Commons ValidateまたはGuava Preconditionsの代替手段を知っていますか ( Spring Assertを除く)。


私はJavadocsが言うことを知っています:

アプリケーションは、このクラス [NullPointerException] のインスタンスをスローして、null オブジェクトの他の不正な使用を示す必要があります。

それにもかかわらず、私はそれが好きではありません。私にとって、NPE は常にどこかで null 参照を確保するのを忘れていたことを意味していました。私の目は非常に訓練されており、1 秒あたり数ページの速度でログを閲覧しているのを見つけることができました。そうすると、頭の中で常にバグ アラートが有効になっています。したがって、IllegalArgumentException が予想される場所でスローされると、かなり混乱します。

私が豆を持っているとしましょう:

public class Person {
  private String name;
  private String phone;
  //....
}

およびサービスメソッド:

public void call(Person person) {
  //assert person.getPhone() != null
  //....
}

状況によっては、人が電話を持っていなくても問題ない場合があります (私のおばあちゃんは電話を持っていません)。しかし、そのような人に電話をかけたい場合は、 IllegalArgumentを渡してcallメソッドを呼び出すことです。階層を見てください - NullPointerException は IllegalArgumentException のサブクラスでさえありません。基本的には、null 参照で getter を呼び出そうとしました

その上、すでに議論があり、私が完全に支持するこの素晴らしい答えがあります. だから私の質問はただ - 私はこのような醜いことをする必要がありますか?

Validate.isTrue(person.getPhone() != null, "Can't call a person that hasn't got a phone");

または、notNull チェックのために IllegalArgumentException をスローするだけのライブラリはありますか?

4

7 に答える 7

0

私が知っているわけではありません。簡潔な呼び出しで必要な動作を取得するために独自のロールを作成し、Guava の実装を模倣しながら例外の種類を微調整します。

class Preconditionz {
    public static <T> T checkNotNull(T reference, Object errorMessage) {
        if (reference == null) {
            throw new IllegalArgumentException(String.valueOf(errorMessage));
        }
        return reference;
    }
}

私は先に進むのが好きで、import staticこれらの非常に頻繁に使用されるメソッドも非常に簡潔に呼び出すことができるようにします。

import static com.whatever.util.Preconditionz.checkNotNull;

// ...

public void call(Person person) {
    checkNotNull(person, "person");
    checkNotNull(person.getPhone(), "person.phone");
    // ...
}

環境によってはcheckNotNull2、IDE でオートコンプリートを介してインポートを簡単に追加したり、標準のcheckNotNull.

于 2015-05-04T20:30:36.233 に答える
0

Olivier Grégoire、Louis Wasserman、CollinD、Captain Man のすばらしいコメントのおかげで、ここ SO でまた何かを学んだようです。標準は通常、共通言語プログラマーが常に正しく理解できるようにするための強力で十分な理由ですが、この特定のケースでは、NPE に関するこのルール セットはあまり適切ではないのではないかと少し疑っていました。Java は古い言語であり、その機能のいくつかは少し不運なものになりました (間違っているとは言いたくないのですが、判断が強すぎる可能性があります)。これで、この疑問は解決されたと思います。次のことを行う必要があります。

  • ビジネスの観点からではなく、特定のコンテキストで null 値が間違っている理由がわかった場合は、IllegalArgumentException をスローします。たとえば、サービス メソッドpublic void call(Person person)では、電話番号が null であることがシステムにとって何を意味するかを知っています。
  • ここのnull値が間違っていて、遅かれ早かれNullPointerExceptionが発生することがわかっている場合は、NullPointerExceptionをスローしますが、特定のコンテキストでは、ビジネスの観点からそれが何を意味するのかわかりません。例は、グアバの不変コレクションです。そのようなものを作成して null 値の要素を追加しようとすると、NPE がスローされます。この値があなたにとって何を意味するのか理解していません。一般的すぎますが、ここで間違っていることを知っているだけなので、問題をより効果的に認識できるように、より適切なメッセージでこれをすぐに伝えることも決定します。

上記を念頭に置いて、public void call(Person person)例でアサーションを行うための最良のオプションは、キャプテンマンが示唆しているようなものです。

Preconditions.checkArgument(person.getPhone() != null, "msg");

引数のチェックは、このメソッドの適切な名前です。引数 person に対してビジネス コントラクトのコンプライアンスをチェックしていることは明らかであり、失敗した場合は IllegalArgumentException が発生することを予期していることは明らかです。これは、Apache Commons の Validate.isTrue よりも適切な名前です。一方、 Validate.notNull または Preconditions.checkNotNull と言うと、null 参照をチェックしていて、実際には NPE を期待していることがわかります。

したがって、最終的な答えは、そのような優れたライブラリはなく、混乱を招くため、そうすべきではありません。(そして、Spring Assert を修正する必要があります)。

于 2015-05-05T07:05:31.483 に答える