6

以下の機能を持っている場合、2つの選択肢があります

private MyObject findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return pieces[i];
        }
    }
    return null;
}

private MyObject findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return pieces[i];
        }
    }
    throw new NoSuchFieldError("No blank piece found!");
}

このメソッドから、「ピース」の1つが常にオブジェクトを返す必要があることがわかりisBlank() == trueます。最後にnullを返すのは、コンパイラを喜ばせるためだけです。これは事実であり、null が返された場合、私のコードはとにかく動作しないため、例外をスローするのは正しいですか?

私のオプションは次のとおりです。

  1. null を返すと、アプリはいくつかのエッジ ケースで NullPointerException を取得します。
  2. null を返し、メソッドの使用を (myObject != null) チェックでラップする
  3. 実行時にそれを爆破する例外をスローします

私が求めているのは、これは例外をスローする正しい場所ですか? つまり、その状況に陥った場合、私にできることは何もありません。これは「例外的」に分類されますか、それともメソッドが返すものを null チェックする必要があります (これにより、コードが恐ろしく見えます)。null を返すべきではないことがわかっている場合は、例外をスローする必要がありますか?

また、どの例外を選択するか、例外を拡張して独自のものをスローするにはどうすればよいですか?

4

10 に答える 10

10

私が求めているのは、これは例外をスローする正しい場所ですか?

例外的な状況であれば、はい。基準に一致するものが見つからない可能性が予想される場合、状況は例外ではなく、戻る必要がありますnull

于 2012-06-03T20:00:40.700 に答える
4

オプションについて、次のことを自問してください。

  1. nullこのメソッドが予期しない値 (つまり)を返した後、ある時点でプログラムを爆発させるのは良い考えですか?
  2. null戻り値をマスクすると何が隠されるのでしょうか?
  3. 間違った値があったからといって、すぐに爆破するのは良い考えですか?

個人的には、質問 2 と 3 のどちらの回答が好きかによって、オプション 2 または 3 を選びます。オプション 1 は、特にそれが発生しない場合は、間違いなく悪い考えです。関数が戻った後にプログラムが NPE ウェイをスローする場合、どこnullから来たのかを理解するのに苦労します。特に、この特定の機能の作業を終了してから数か月後に発生した場合.

例外をスローすることを選択した場合、問題が発生した場所がすぐにわかり、その場所に直接移動して、問題が発生した理由を突き止めることができます。呼び出し元の関数でそれを返しnullてチェックすることもできますが、それは黙って失敗するのではなく、実際に問題を適切に処理するために何かを行う場合に限られます。

于 2012-06-03T20:18:02.530 に答える
4

はい、RuntimeException発生してはならない「例外的な」状況を示すために a をスローする必要があります。IllegalStateExceptionおそらく法案に適合します。バグがスローされた場合にバグを見つけるのに役立つ情報を含むメッセージを必ず含めてください。

于 2012-06-03T19:59:36.567 に答える
1

Null Object patternを使用することをお勧めします。

Provide an object as a surrogate for the lack of an object of a given type. The Null Object provides intelligent do nothing behavior, hiding the details from its collaborators

その場合、例外を使用したり、null を返したりする必要はありません。意図した戻り型オブジェクトをいつでも返すことができます。トリックは、返すものが何もない場合です。null例外を返すかスローする代わりにNull object、意図した戻り値の型と同じ型を返すことができます。

このドキュメントには、いくつかの例と説明があります。あなたと同じようなケースがあり、デザインパターンによって解決されます。

public class CustomerFactory {

  public static final String[] names = {"Rob", "Joe", "Julie"};

  public static AbstractCustomer getCustomer(String name){   
    for (int i = 0; i < names.length; i++) {
       if (names[i].equalsIgnoreCase(name)){
         return new RealCustomer(name);
       }
    }
    return new NullCustomer();
  }
}
于 2016-10-06T06:15:37.470 に答える
0

常にオブジェクトを返すかnull
を返す必要が あり
、アプリはNullPointerException
これら2つが矛盾するエッジケースを取得します。

あなたがいつも持っていると本当に確信しているならpieces[i].isBlank()、投げてくださいIllegalStateException

それ以外の場合は、要件に従ってケースを処理してください。

于 2012-06-03T20:01:48.890 に答える
0

配列が常に有効な値を返す必要がある場合は、フォールバックとして例外を発生させる必要があります。(あなたの例では2番目のケース)

最終的には、独自の種類 (クラス) の例外を宣言できます。

于 2012-06-03T20:04:08.450 に答える
0

少し前に別の回答で話したMaybe(としても知られる) データ型を使用することをお勧めします。Option

このデータ型Functional Javaで使用できます。

使用法:

private Option<MyObject> findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return Option.some(pieces[i]);
        }
    }
    return Option.none();
}

サイドノート:

メソッドは、述語を引数として取り、それを満たす最初の要素を見つけて返すfindBackメソッドに一般化できます。

当然のことながら、Functional Java にはすでにそれもあります

piecesであると仮定しましょうfj.data.List。次に、メソッドを次のように書き換えることができます。

private Option<MyObject> findBlank() {
  return pieces.find(new F1<MyObject, Boolean>() {
    public Boolean f(MyObject p) {
      return p.isBlank();
    }
  });
}

別の補足:

おそらく、上記のコードはかなり危険に見えます。ここでは、IntelliJ IDEA の「クロージャーの折りたたみ」が役立ちます

于 2012-06-03T20:25:45.697 に答える