531

私はJava言語を使用しています。オブジェクトが見つかった場合にオブジェクトを返すメソッドがあります。

見つからない場合は、次のことを行う必要があります。

  1. null を返す
  2. 例外をスローする
  3. 他の

ベストプラクティスまたはイディオムはどれですか?

4

36 に答える 36

509

常に値が見つかることを期待している場合は、値が見つからない場合に例外をスローします。例外は、問題があったことを意味します。

値が欠落しているか存在している可能性があり、両方がアプリケーション ロジックに対して有効な場合は、null を返します。

さらに重要: コードの他の場所で何をしますか? 一貫性が重要です。

于 2008-10-06T18:21:50.410 に答える
104

本当にエラーである場合にのみ、例外をスローします。オブジェクトが存在しないことが予期される動作である場合は、null を返します。

それ以外は好みの問題です。

于 2008-10-06T18:21:36.277 に答える
77

時折のヌルを予測し、特定の方法でそれを処理したい場合は、ヌルを使用してください。

何をするにせよ、3 番目のオプションである「WTF」という文字列を返すことは強くお勧めしません。

于 2008-10-06T18:22:30.300 に答える
52

null がエラーを示さない場合は、単に null を返します。

null が常にエラーの場合は、例外をスローします。

null が例外になる場合がある場合は、2 つのルーチンをコーディングします。1 つのルーチンは例外をスローし、もう 1 つは出力パラメーターでオブジェクトを返すブール テスト ルーチンであり、オブジェクトが見つからない場合、ルーチンは false を返します。

Try ルーチンを誤用することは困難です。null のチェックを忘れがちです。

したがって、 null がエラーの場合は、次のように記述します

object o = FindObject();

null がエラーでない場合は、次のようにコーディングできます。

if (TryFindObject(out object o)
  // Do something with o
else
  // o was not found
于 2008-10-06T18:52:05.967 に答える
27

前に述べたオプションを要約し、いくつかの新しいオプションを追加したかっただけです。

  1. null を返す
  2. 例外をスローする
  3. null オブジェクト パターンを使用する
  4. メソッドにブール値のパラメーターを提供して、呼び出し元が例外をスローするかどうかを選択できるようにします
  5. 追加のパラメーターを提供して、値が見つからない場合に呼び出し元が値を設定できるようにする

または、これらのオプションを組み合わせることができます。

ゲッターのオーバーロードされたバージョンをいくつか提供して、呼び出し元がどちらに進むかを決定できるようにします。ほとんどの場合、最初のものだけが検索アルゴリズムを実装しており、他のものは最初のものをラップするだけです:

Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);

実装を 1 つだけ提供することを選択した場合でも、そのような命名規則を使用してコントラクトを明確にすることをお勧めします。これは、他の実装も追加することにした場合に役立ちます。

過度に使用するべきではありませんが、多くの異なるエラー処理規則を持つ何百もの異なるアプリケーションで使用するヘルパー クラスを作成する場合に特に役立ちます。

于 2009-01-04T18:00:52.787 に答える
19

null オブジェクト パターンを使用するか、例外をスローします。

于 2008-10-06T18:21:04.687 に答える
15

例外をスローする利点:

  1. 呼び出しコードの制御フローがより明確になります。 null をチェックすると、try/catch によってネイティブに処理される条件分岐が挿入されます。null のチェックは、何をチェックしているのかを示していません。予想されるエラーを探しているために null をチェックしているのか、それともダウンチェーンでそれ以上渡さないように null をチェックしているのか?
  2. 「null」の意味のあいまいさを取り除きます。 null はエラーを表しているのか、実際に値に格納されているのは null なのか? その決定の根拠となることが1つしかない場合、言うのは難しい.
  3. アプリケーション内のメソッド動作間の一貫性が向上しました。 通常、例外はメソッド シグネチャで公開されるため、アプリケーションのメソッドが説明するエッジ ケースと、アプリケーションが予測可能な方法で反応できる情報をよりよく理解できます。

例を含む詳細な説明については、http: //metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/を参照してください。

于 2011-11-17T05:35:54.863 に答える
13

言語とコードが促進するかどうかによって異なります。

LBYL は、値を確認する必要があることを示しています (したがって、null を返します)
。EAFP は、操作を試行して失敗するかどうかを確認するように指示します (例外をスローします)。

上記には同意しますが、例外/エラー条件には例外を使用する必要があり、チェックを使用する場合は null を返すのが最適です。


Python での EAFP と LBYL の比較:
http://mail.python.org/pipermail/python-list/2003-May/205182.html ( Web アーカイブ)

于 2008-10-06T19:22:00.070 に答える
13

使用している API と一貫性を保ちます。

于 2008-10-06T18:20:53.503 に答える
13

「オブジェクトが見つからないのは例外的なケースですか?」と自問してみてください。プログラムの通常の過程で発生することが予想される場合は、おそらく例外を発生させないでください (例外的な動作ではないため)。

短いバージョン: 例外を使用して、プログラム内の通常の制御フローを処理するのではなく、例外的な動作を処理します。

-アラン。

于 2008-10-06T22:16:57.550 に答える
6

例外は、契約による設計に関連しています。

オブジェクトのインターフェースは、実際には2つのオブジェクト間のコントラクトであり、呼び出し元はコントラクトを満たす必要があります。そうでない場合、受信者は例外を除いて失敗する可能性があります。2つの可能な契約があります

1)メソッドのすべての入力が有効です。この場合、オブジェクトが見つからない場合はnullを返す必要があります。

2)一部の入力のみが有効です。つまり、オブジェクトが見つかりました。その場合、呼び出し元が入力が正しいかどうかを判断できる2番目のメソッドを提供する必要があります。例えば

is_present(key)
find(key) throws Exception

2番目のコントラクトの両方のメソッドを提供する場合にのみ、例外をスローすることが許可されます。何も見つかりません。

于 2008-10-06T23:37:56.747 に答える
4

さらにいくつかの提案があります。

コレクションを返す場合は、null を返さないようにし、最初に null チェックを行わずに列挙を処理しやすくする空のコレクションを返します。

いくつかの .NET API は、オブジェクトが見つからない場合に本当に例外的な状況であるかどうかを呼び出し元に選択させる throwOnError パラメーターのパターンを使用します。Type.GetType はこの例です。BCL のもう 1 つの一般的なパターンは、ブール値が返され、値が出力パラメーターを介して渡される TryGet パターンです。

状況によっては、デフォルトまたは動作のないバージョンのいずれかである Null Object パターンを検討することもできます。重要なのは、コード ベース全体で null チェックを避けることです。詳細については、こちらを参照してください http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx

于 2008-10-07T00:07:22.977 に答える
4

オブジェクトが見つからないことの意味によって異なります。

通常の状態である場合は、null を返します。これは、たまに発生する可能性があるものであり、発信者はそれを確認する必要があります。

エラーの場合、例外をスローする場合、発信者は、オブジェクトの欠落のエラー条件で何をすべきかを決定する必要があります。

最終的にはどちらでも機能しますが、ほとんどの人は一般的に、例外が発生した場合にのみ例外を使用することをお勧めします。

于 2008-10-06T18:22:42.657 に答える
3

例外をスローする代わりに null を返し、API ドキュメントで null の戻り値の可能性を明確に文書化します。呼び出し元のコードが API を尊重せず、null のケースをチェックしない場合、何らかの「null ポインター例外」が発生する可能性が最も高いでしょう :)

C++ では、オブジェクトを検索するメソッドを設定する 3 つの異なるフレーバーを考えることができます。

オプション A

Object *findObject(Key &key);

オブジェクトが見つからない場合は null を返します。素敵でシンプル。私はこれで行きます。以下の代替アプローチは、out-params を嫌わない人向けです。

オプション B

void findObject(Key &key, Object &found);

オブジェクトを受け取る変数への参照を渡します。オブジェクトが見つからない場合、メソッドは例外をスローしました。この規則は、オブジェクトが見つからないことが実際には予想されない場合に適している可能性があります。そのため、予期しないケースであることを示すために例外をスローします。

オプション C

bool findObject(Key &key, Object &found);

オブジェクトが見つからない場合、メソッドは false を返します。オプション A に対するこの利点は、1 つの明確な手順でエラー ケースを確認できることです。

if (!findObject(myKey, myObj)) { ...
于 2008-10-06T18:28:38.680 に答える
3

null が例外的な動作と見なされない場合のみを参照してください。私は間違いなく try メソッドに賛成です。ここで述べたように、「本を読む」または「ジャンプする前に見る」必要がないことは明らかです

だから基本的に:

bool TryFindObject(RequestParam request, out ResponseParam response)

これは、ユーザーのコードも明確になることを意味します

...
if(TryFindObject(request, out response)
{
  handleSuccess(response)
}
else
{
  handleFailure()
}
...
于 2010-12-22T16:25:45.543 に答える
3

私は単に null を返すことを好み、呼び出し元がそれを適切に処理することに依存しています。(より良い言葉がないため)例外は、このメソッドがオブジェクトを返すことが絶対に「確実」である場合です。その場合、失敗は例外的なはずであり、スローする必要があります。

于 2008-10-06T18:20:32.160 に答える
3

一部の関数では、パラメーターを追加します。

..., bool verify = true)

true はスローを意味し、false は何らかのエラー戻り値を返すことを意味します。このように、この関数を使用する人は誰でも両方のオプションを利用できます。エラー処理を忘れている人のために、デフォルトは true にする必要があります。

于 2008-10-06T20:00:19.730 に答える
2

またはオプションを返す

オプションは基本的に、クライアントにブース ケースの処理を強制するコンテナ クラスです。Scala にはこの概念があります。その API を調べてください。

次に、このオブジェクトに T getOrElse(T valueIfNull) のようなメソッドがあり、見つかったオブジェクトを返すか、クライアント指定の代替案を返します。

于 2008-10-06T19:04:45.147 に答える
2

If it's important for client code to know the difference between found and not found and this is supposed to be a routine behavior, then it's best to return null. Client code can then decide what to do.

于 2008-10-06T18:21:21.347 に答える
2

nullを返すことを好む -

呼び出し元がチェックせずにそれを使用すると、いずれにしても例外がすぐに発生します。

呼び出し元が実際に使用しない場合は、try/catchブロックに課税しないでください。

于 2011-02-23T06:02:23.633 に答える
2

通常、null を返す必要があります。メソッドを呼び出すコードは、例外をスローするか、別のことを試みるかを決定する必要があります。

于 2008-10-06T18:21:25.060 に答える
2

残念ながら、JDK には一貫性がありません。リソース バンドルに存在しないキーにアクセスしようとすると、見つからないという例外が発生し、マップから値を要求すると、存在しない場合は null が返されます。したがって、勝者の回答を次のように変更します。見つかった値がnullになる可能性がある場合は、見つからない場合は例外を発生させ、そうでない場合はnullを返します。したがって、値が見つからない理由を知る必要がある場合は、常に例外を発生させるか、1 つの例外を除いてルールに従います。

于 2011-08-03T00:32:52.190 に答える
1

メソッドがコレクションを返す場合は、空のコレクションを返します(上記のように)。ただし、Collections.EMPTY_LISTなどは使用しないでください。(Javaの場合)

メソッドが単一のオブジェクトを取得する場合、いくつかのオプションがあります。

  1. メソッドが常に結果を見つける必要があり、オブジェクトが見つからないことが実際の例外の場合は、例外をスローする必要があります(Javaの場合:チェックされていない例外を指定してください)
  2. (Javaのみ)メソッドがチェックされた例外をスローすることを許容できる場合は、プロジェクト固有のObjectNotFoundExceptionなどをスローします。この場合、例外を処理するのを忘れた場合、コンパイラはあなたに通知します。(これは、Javaで見つからないものの私の好ましい処理です。)
  3. 本当に問題ないと言った場合、オブジェクトが見つからず、メソッド名がfindBookForAuthorOrReturnNull(..)のようであれば、nullを返すことができます。この場合、ある種の静的チェックまたはコンパイラチェックを使用することを強くお勧めします。これにより、nullチェックなしで結果の逆参照が防止されます。Javaの場合は、たとえば次のようになります。FindBugs(http://findbugs.sourceforge.net/manual/annotations.htmlのDefaultAnnotationを参照)またはIntelliJ-Checking。

nullを返すことにした場合は、注意してください。プロジェクトのプログラマーがあなただけではない場合、実行時にNullPointerExceptions(Javaまたは他の言語の何か)が発生します。したがって、コンパイル時にチェックされないnullを返さないでください。

于 2012-08-21T13:13:22.377 に答える
1

例外処理のオーバーヘッドについて誰も言及していないと思います-例外をロードして処理するために追加のリソースが必要になるため、真のアプリの強制終了またはプロセス停止イベント(今後は良いよりも害をもたらす)でない限り、私はパスバックすることを選択します呼び出し環境が適切と考える値を解釈できます。

于 2008-10-06T18:29:42.407 に答える
1

ここでのコンセンサスと思われるものに同意します(「見つからない」が通常の可能な結果である場合はnullを返すか、状況のセマンティクスでオブジェクトが常に見つかる必要がある場合は例外をスローします)。

ただし、特定の状況に応じて意味をなす可能性のある3番目の可能性があります。メソッドは、「見つからない」状態である種のデフォルトオブジェクトを返すことができます。これにより、呼び出し元のコードは、nullチェックや例外キャッチを必要とせずに常に有効なオブジェクトを受け取ることが保証されます。

于 2008-10-06T18:36:04.890 に答える
1

null を返します。例外はまさにそれです。コードが予期しないことを行うことです。

于 2008-10-06T19:09:04.933 に答える
1

オブジェクトへの参照を返すことになっている限り、NULL を返すことは良いことです。

ただし、血まみれのもの全体を返す場合 (C++ のように、「return &blah;」ではなく「return blah;」(または「blah」がポインター) の場合、NULL を返すことはできません。その場合、例外をスローするか、成功フラグが設定されていない空のオブジェクトを返すことが、問題に対処する方法です。

于 2008-10-06T18:23:26.227 に答える
1

例外は例外的であるべきです。nullを返すことが有効な場合は null を返します

于 2008-10-06T22:26:07.250 に答える
0

データレイヤーコードでは、次のコードを使用することがあります。これにより、呼び出し元は、「オブジェクトが見つかりません」がエラーが発生したことを意味するかどうかを判断できます。


DataType GetObject(DBConnection conn, string id, bool throwOnNotFound) {
    DataType retval = ... // find object in database
    if (retval != null || ! throwOnNotFound) {
        return retval;
    } else {
        throw new NoRowsFoundException("DataType object with id {id} not found in database");
    }
}

DataType GetObject(DBConnection conn, string id) {
    return GetObject(conn, id, true);
} 
于 2008-10-06T18:42:29.293 に答える
0

オブジェクトが含まれていないことは、通常の操作中に発生する可能性があり、呼び出し元が NULL を返すことで処理する必要があります。

オブジェクトが含まれていないことが、呼び出し元のコードまたは内部状態によるバグを示している場合は、アサートを実行します。

オブジェクトが含まれていない場合は、まれなイベントを示します。(アイテムを同時にチェックアウトしているときに、誰かがストアからアイテムを削除したようなものです。) 次に、例外をスローします。

于 2008-10-06T20:07:38.217 に答える
0

それは、オブジェクトが見つかるかどうかに大きく依存します。何かを示すために例外を使用する必要があるという考え方に従う場合、例外が発生したことになります。

  • オブジェクトが見つかりました。オブジェクトを返す
  • オブジェクトが見つかりません。例外をスローする

それ以外の場合は、null を返します。

于 2008-10-06T18:21:33.657 に答える
0

これは、メソッドの性質と使用方法によって異なります。オブジェクトが見つからないことが通常の動作である場合は、null を返します。オブジェクトが常に見つかることが通常の動作である場合は、例外をスローします。

経験則として、例外は何か例外が発生した場合にのみ使用してください。例外のスローとキャッチが通常の操作の一部になるようにコードを記述しないでください。

于 2008-10-06T18:22:48.803 に答える
0

それが例外的なイベントであると判断されない場合 (つまり、通常の状況では存在するはずです)、スローします。それ以外の場合は、"not found" 値 (null の場合もありますが、null にする必要はありません) を返すか、メソッドが found/notfound のブール値と実際のオブジェクトの out パラメーターを返すようにします。

于 2008-10-06T18:23:31.250 に答える
0

それはあなたの方法に依存します。メソッドが常に有効なオブジェクトを返すことになっていて、何も見つからない場合は、例外をスローする方法があります。メソッドが、存在するかどうかわからないオブジェクト (連絡担当者の画像など) を返すだけの場合は、エラーを発生させるべきではありません。

このメソッドが実際にオブジェクトを返す場合は、ブール値の true/false を返すメソッドを公開して、a) null をチェックするか、b) 例外をキャッチする必要がない場合もあります。

于 2008-10-06T18:23:31.483 に答える
0

「その他」のオプションは、検索されたオブジェクトが見つからない場合に返されるデフォルト オブジェクトを含む追加のパラメータを find メソッドに持たせることです。

それ以外の場合は、オブジェクトが見つからないという例外的なケースでない限り、null を返します。

于 2008-10-06T18:25:20.170 に答える