57

最近、私の同僚が、メソッド全体のヌル ポインター例外をキャッチし、単一の結果を返すコードを作成しました。ヌル ポインターにはさまざまな理由が考えられることを指摘したので、1 つの結果に対する防御的なチェックに変更しました。

ただし、 NullPointerException をキャッチすることは、私には間違っているように思えました。私の考えでは、Null ポインター例外は不適切なコードの結果であり、システムで予期される例外ではありません。

null ポインター例外をキャッチすることが理にかなっているケースはありますか?

4

18 に答える 18

37

はい、RuntimeExceptionほとんどの場合、コードの匂いがします。C2 Wikiは同意しているようです。

例外は、おそらく、他のモジュールからかなりランダムなコードを実行する特別に防御的なコードの一部です。このような防御構造の例は、EDT、 ThreadPools/Executors 、およびプラグイン システムです。

于 2010-04-06T16:04:30.233 に答える
25

をキャッチするための用途は、1 つだけ考えられますNullPointerException

catch (NullPointerException) {
    ApplyPainfulElectricShockToProgrammer();
}
于 2010-04-06T17:46:41.097 に答える
15

サード パーツ ライブラリのバグが原因で、時々 nullpointer 例外をキャッチする必要がありました。私たちが使用したライブラリはその例外をスローしましたが、それに対して私たちができることは何もありませんでした.

その場合はキャッチしても問題ありませんが、そうでない場合は問題ありません。

于 2010-04-06T16:40:31.430 に答える
7

場合によります。

この同僚の経験はどれくらいですか? 彼は無知/怠惰のためにこれをやっているのですか、それとも本当に正当な理由がありますか? (これが何よりもメインスレッドであり、死ぬことはありませんか?)

実行時例外をキャッチするのは 90% の確率で間違っており、NullPointerException をキャッチするのは 99% 間違っています (理由が「大量の例外を取得していた...」という 場合は、プログラマー全体が間違っているため、注意する必要があります。彼が行っているコードの残りの部分)

ただし、状況によっては、NullPointerException をキャッチしても問題ない場合があります。

于 2010-04-06T16:12:06.910 に答える
3

悪いことですが、最適化されたバイトコードを生成できます。

Integeriがほとんどの場合ではない場合null、check は全体的なパフォーマンスを低下させます。チェック自体には 3 つの命令 (0 ~ 4) が必要です。ケース全体で 7 つの命令 (0 ~ 14) を使用します。

public class IfNotNull {

    public Integer i;

    public String getIAsString() {
        if (i != null) {
            return i.toString();
        } else {
            return "";
        }
    }
}

  public java.lang.String getIAsString();
    Code:
       0: aload_0       
       1: getfield      #2                  // Field i:Ljava/lang/Integer;
       4: ifnull        15
       7: aload_0       
       8: getfield      #2                  // Field i:Ljava/lang/Integer;
      11: invokevirtual #3                  // Method java/lang/Integer.toString:()Ljava/lang/String;
      14: areturn       // <- here we go
      15: ldc           #4                  // String 
      17: areturn 

Python の世界で一般的な EAFP アプローチに従います。ケースはコストがかかりますが、nullケースには 4 つの命令 (0 ~ 7) しか必要ありませんnot null

public class TryCatch {

    public Integer i;

    public String getIAsString() {
        try {
            return i.toString();
        } catch (NullPointerException npe) {
            return "";
        }
    }
}

  public java.lang.String getIAsString();
    Code:
       0: aload_0       
       1: getfield      #2                  // Field i:Ljava/lang/Integer;
       4: invokevirtual #3                  // Method java/lang/Integer.toString:()Ljava/lang/String;
       7: areturn       // <- here we go
       8: astore_1      
       9: ldc           #5                  // String a
      11: areturn       
    Exception table:
       from    to  target type
           0     7     8   Class java/lang/NullPointerException

JITコンパイラがこれを最適化できるかどうか、誰が知っていますか?

于 2014-02-27T16:54:46.867 に答える
3

面白い

仕事でやってはいけないことを見つけました。

public static boolean isValidDate(final String stringDateValue) {
    String exp = "^[0-9]{2}/[0-9]{2}/[0-9]{4}$";
    boolean isValid = false;
    try {
        if (Pattern.matches(exp, stringDateValue)) {
            String[] dateArray = stringDateValue.split("/");
            if (dateArray.length == 3) {
                GregorianCalendar gregorianCalendar = new GregorianCalendar();
                int annee = new Integer(dateArray[2]).intValue();
                int mois = new Integer(dateArray[1]).intValue();
                int jour = new Integer(dateArray[0]).intValue();

                gregorianCalendar = new GregorianCalendar(annee, mois - 1,
                        jour);
                gregorianCalendar.setLenient(false);
                gregorianCalendar.get(GregorianCalendar.YEAR);
                gregorianCalendar.get(GregorianCalendar.MONTH);
                gregorianCalendar.get(GregorianCalendar.DAY_OF_MONTH);
                isValid = true;
            }
        }
    } catch (Exception e) {
        isValid = false;
    }
    return isValid;
}

悪い:)

開発者は、カレンダーでこの種の例外を発生させたいと考えていました。

java.lang.IllegalArgumentException: DAY_OF_MONTH
    at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:2316)
    at java.util.Calendar.updateTime(Calendar.java:2260)
    at java.util.Calendar.complete(Calendar.java:1305)
    at java.util.Calendar.get(Calendar.java:1088)

値を無効にするには...

はい、機能しますが、実際には良い習慣ではありません...

例外を発生させる (特にスタック トレースを埋める) には、例外なしでデータを手動でチェックするよりもはるかに多くのコストがかかります...

于 2010-04-07T14:40:52.180 に答える
3

一般的に、これはコードの匂いだと思います。防御チェックの方が優れているように思えます。レポート/ロギングのためにすべてのエラーをキャッチしたいイベントループなどを除いて、ほとんどの未チェックの例外をカバーするように拡張します。

私が考えることができる例外は、変更できず、事前にチェックするのが難しいアサーションの失敗に応答してヌル ポインター例外を生成する可能性があるライブラリへの呼び出しに関するものです。

于 2010-04-06T16:03:36.987 に答える
2

確かにそうです。

ほとんどの場合、最初から変数を null にするべきではありません。多くの新しい言語では、null 非許容参照型 (つまり、決して null にならないことが保証されている型) のサポートが組み込まれています。

入力値が null になることが許可されている場合は、チェックを行う必要があります。しかし、例外はこれを行うための間違いなく悪い方法です。

if ステートメントは、おそらく 3 つの命令を実行する必要があり、ローカル チェックです (つまり、保証が必要な場所でチェックを行います)。

一方、例外を使用すると、さらに多くの命令が必要になる場合があります。システムはメソッドを検索しようとして失敗し、例外テーブルを調べて適切な例外ハンドラーを探し、そこにジャンプし、ハンドラーを実行して、再びジャンプします。さらに、チェックは非ローカルである可能性があります。コードが次のような場合:

try
  return contacts.find("Mom").getEmail()
catch (NullPointerException e)
  return null

NPE が「getEmail」でスローされたのか「find」でスローされたのかわかりません。

より難読化された方法で書かれた非常に一般的なパターンに対する技術的に悪い解決策はありますか? ランクではありませんが、確かに臭いです:/

于 2010-04-06T16:16:44.710 に答える
2

プログラムが完全にクラッシュせずに回復できるように、NullPointerException (または具体的にはすべての Throwable) をキャッチする必要がある唯一の場所は、トップレベルまたはシステムの境界です。たとえば、web.xml でエラー ページを設定すると、キャッチオールが提供され、Web アプリケーションが例外から回復してユーザーに通知できるようになります。

于 2010-04-06T16:48:48.787 に答える
1

Swing-GUI ベースのアプリケーションを正常に終了するには、NPE (実際にはすべての RTE) をキャッチする必要があります。

edit : この場合、通常は UncaughtExceptionHandler を介して行われます。

于 2010-04-06T20:40:29.950 に答える
1

ずっと前に、私は1つの使用をしました。特に愚かなライブラリは、キーによってコレクション内のオブジェクトを要求され、オブジェクトが見つからない場合に NullPointerException をスローします。キーで検索する以外に検索する方法はなく、オブジェクトが存在するかどうかを確認する方法もありませんでした。

しばらくして、ベンダーを起動し、ライブラリの変更を開始しました。現在、ライブラリはより適切な例外 (私の変更) をスローし、チェック機能 (他の誰かの変更) を備えています。

もちろん、try ブロック内の行は常に 1 行だけになります。これ以上、私自身が悪いコードの罪を犯すでしょう。

于 2010-04-06T18:25:48.600 に答える
1

これはどうですか:

try
{
    foo.x = bar;
}
catch (NullPointerException e)
{
    // do whatever needs to be done
}

foo が null である可能性がある場合のマイクロ最適化として、しかしほとんどありませんか?

アイデアは次のとおりです。

  • 明示的な NULL チェックは、単一のマシン命令を必要とします

  • 一方、2 番目のバージョンの NULL チェックは、NULL アクセスを発生させ、SIGSEGV をキャッチし、NullPointerException をスローすることで実行できます。オブジェクトが NULL でない場合、これはフリーです。

于 2013-12-21T11:47:15.670 に答える
1

NULL ポインター例外のキャッチは、実際にはコンテキストに依存します...厳密な絶対規則を回避するよう努める必要があります...規則はコンテキストに適用する必要があります-この例外をトラップし、ソフトウェア全体をいくつかの STABLE 状態に置きたいです-何もしないか、ほとんど何もしませんほとんど何もない。そのようなコーディング規則はすべてよく理解する必要があります

この時点で、ソフトウェアの AUDIT TRACE ... を調べて、この例外のソースを発見する必要があります。

NULL ポインター例外は決して発生しないという考えは、検証可能でなければなりません。最初に静的分析を行います...(サードパーティのコード/コンポーネントが入ってくるとより困難になります)次に、関連するツールを使用して徹底的な状態空間検索を行います。

バツ

于 2010-04-06T18:45:40.137 に答える
0

インターフェイスからの結果を保証しようとしますが、一部のライブラリまたは誰かのコードが結果として null を生成する可能性があり、それをキャッチする保証が実行可能であると期待している場合。もちろん、捕まえたらどうするかはあなた次第です。場合によっては、null をチェックしても意味がないことがあります。それを見つけた場合は、問題を解決する別の方法があります。これは、それほど良くはないかもしれませんが、仕事は完了します。

私が言っているのは、可能な限り例外を使用することです。これは非常に優れた言語機能です。

于 2010-04-06T16:29:08.370 に答える
0

NullPointerException のキャッチは、メソッドが外部インターフェイス (または SOAP API) を呼び出し、返される値が Null である可能性がある場合に役立ちます。それ以外には、これらの例外をキャッチしても大きなメリットはありません。

于 2010-04-06T17:03:14.620 に答える
0

それは本当にインターフェース定義に依存します。非構造化 NPE の処理は、Exception または Throwable をキャッチするのと同じくらい悪いものです。

Null は、空の文字列や max_int などを使用するのではなく、初期化されていない状態を識別するのに役立ちます。null を定期的に使用する場所は、コールバック オブジェクトが関連しない場所です。

Guice が提供する @Nullable アノテーションがとても気に入っています。

http://code.google.com/docreader/#p=google-guice&s=google-guice&t=UseNullable

コードベースで NullPointerExceptions を排除するには、null 参照について訓練する必要があります。以下の単純なルールを適用することで、これに成功しました。

明示的に指定されていない限り、すべてのパラメーターは null ではありません。Google Collections ライブラリと JSR-305 には、null を制御するための単純な API があります。Preconditions.checkNotNull を使用して、null 参照が見つかった場合に高速失敗させることができます。また、@Nullable を使用して、null 値を許可するパラメーターに注釈を付けることができます。

Guice はデフォルトで null を禁止します。null の注入を拒否し、代わりに ProvisionException で失敗します。クラスで null が許可されている場合は、@Nullable でフィールドまたはパラメーターに注釈を付けることができます。Guice は、edu.umd.cs.findbugs.annotations.Nullable や javax.annotation.Nullable などの @Nullable 注釈を認識します。

于 2010-04-06T17:36:46.980 に答える
0

はい、Java では NullPointerException をチェックする必要があります。

オブジェクトが必要な場合に、アプリケーションが null を使用しようとするとスローされます。これらには以下が含まれます:

null オブジェクトのインスタンス メソッドの呼び出し。null オブジェクトのフィールドへのアクセスまたは変更。null の長さを配列であるかのように取得します。配列であるかのように null のスロットにアクセスまたは変更します。Throwable 値であるかのように null をスローします。

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

レコードが正しい ASCII 文字およびレコード形式で検証されていないテキスト ファイル (つまり、XML) を読み取るときに、他の言語で NullPointerException が発生します。

于 2010-04-06T18:43:34.520 に答える
0

プログラマーが初心者の場合、すべての例外をキャッチする習慣があり、最終的な出力が得られないことがあります。これは、コード レビュー担当者が楽しむべきではありません。

RuntimeException をキャッチするのはよくありません。しかし、それが本当に必要な場合は、コード内のコメントは、そのコードで作業する将来のプログラマーにとって非常に役立ちます。それらをキャッチするための合理的なコメントを書くことができない場合は、それらを避ける必要があります. 限目。

于 2016-09-25T14:55:52.050 に答える