web-dev-qa-db-ja.com

アサーションを使用する場合と例外を使用する場合

ほとんどの場合、例外を使用してコード内の条件を確認しますが、アサーションを使用するのに適切なタイミングはいつですか?

例えば、

Group group=null;
try{
    group = service().getGroup("abc");
}catch(Exception e){
    //I dont log error because I know whenever error occur mean group not found
}

if(group !=null)
{
    //do something
}

ここにアサーションがどのように適合するかを示していただけますか?アサーションを使用する必要がありますか?

実稼働コードではアサーションを使用せず、単体テストではアサーションのみを参照するようです。ほとんどの場合、例外を使用して上記のようなチェックを行うことができることは知っていますが、「専門的に」それを行う適切な方法を知りたいです。

112
cometta

アサーションを使用して、発生しないはずの何かをチェックし、例外を使用して、発生する可能性のある何かをチェックする必要があります。

たとえば、関数は0で除算される可能性があるため、例外を使用する必要がありますが、アサーションを使用してハードドライブが突然消えることを確認できます。

アサーションはプログラムの実行を停止しますが、例外はプログラムの実行を継続させます。

if(group != null)はアサーションではなく、単なる条件であることに注意してください。

79
Marius

私の考えでは(リストは不完全で、コメントに収まるには長すぎるかもしれません)、私は言うでしょう:

  • パブリックまたは保護されたメソッドとコンストラクターに渡されるパラメーターをチェックするときに例外を使用します
  • ユーザーと対話するとき、またはクライアントコードが例外的な状況から回復することを期待するときに例外を使用する
  • 例外を使用して、発生する可能性のある問題に対処する
  • プライベート/内部コードの事前条件、事後条件、および不変条件をチェックするときにアサーションを使用します
  • アサーションを使用して、ご自身または開発者チームにフィードバックを提供します
  • 発生する可能性が非常に低いことをチェックするときにアサーションを使用します。そうしないと、アプリケーションに重大な欠陥があることを意味します
  • アサーションを使用して、(おそらく)真実であることがわかっていることを述べる

つまり、例外はアプリケーションの堅牢性に対処し、アサーションはその正確性に対処します。

アサーションは書くのが安くなるように設計されており、ほとんどどこでも使用できます。私はこの経験則を使用しています。正しい方法で動作しないプログラムをデバッグする場合、経験に基づいて、明らかな障害の可能性を確実に確認します。次に、発生しない問題を確認します。これはまさに、アサーションが多くの時間を節約するのに役立つときです。

161
Gregory Pakosz

アサーションは、パラメーターを使用して実行時に無効にできること、および デフォルトでは無効になっています を忘れないでください。

また、 アサートに関するOracleの記事 を読んで、アサートを使用する(または使用しない)ケースをさらに確認する必要があります。

25
chburd

原則として:

  • アサーションを使用して、内部の整合性チェックを行います。誰かがそれらをオフにした場合、それはまったく重要ではありません。 (Javaコマンドは、デフォルトですべてのアサーションをオフにすることに注意してください。)
  • オフにしてはならないあらゆる種類のチェックに定期的なテストを使用します。このincludesバグによる潜在的な損害の原因、および検証データ/要求/ユーザーまたは外部サービスによって提供されるものを保護する防御チェック。

あなたの質問からの次のコードは悪いスタイルですand潜在的にバグがあります

_try {
    group = service().getGroup("abc");
} catch (Exception e) {
    //i dont log error because i know whenever error occur mean group not found
}
_

問題は、例外がグループが見つからなかったことを意味することを知らないということです。 service()呼び出しが例外をスローした、またはnullを返したときにNullPointerExceptionが発生した可能性もあります。

「予想される」例外をキャッチするときは、only期待する例外をキャッチする必要があります。 _Java.lang.Exception_をキャッチすることにより(特にログに記録しないことにより)、問題の診断/デバッグが難しくなり、アプリがより多くの損害を与える可能性があります。

15
Stephen C

マイクロソフトに戻って、推奨事項は、公開するすべてのAPIで例外をスローし、内部のコードについて行うあらゆる種類の仮定でアサートを使用することでした。定義は少し緩いですが、線を引くのは各開発者次第だと思います。

例外の使用に関して、名前が示すように、その使用法は例外的である必要があるため、上記のコードでは、getGroup呼び出しはサービスが存在しない場合はnullを返します。例外は、ネットワークリンクがダウンした場合などにのみ発生します。

結論は、アプリケーションごとにアサートと例外の境界を定義するのは開発チームに少し任されていると思います。

3
rui

このドキュメントによると http://docs.Oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general 、「assertステートメントは非公開の事前条件、事後条件、およびクラス不変条件のチェック。パブリックな事前条件のチェックは、IllegalArgumentExceptionやIllegalStateExceptionなどの特定の文書化された例外をもたらすメソッド内のチェックによって実行する必要があります。

前提条件、事後条件、クラス不変条件について詳しく知りたい場合は、このドキュメントを確認してください: http://docs.Oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-条件 。また、アサーションの使用例も含まれています。

3
cesarsalgado

Nullのテストでは、問題の原因となっているnullのみがキャッチされますが、try/catchを使用すると、anyエラーがキャッチされます。

概して、try/catchはより安全ですが、わずかに遅いため、発生する可能性のあるあらゆる種類のエラーをキャッチするように注意する必要があります。したがって、try/catchを使用すると言います。ある日、getGroupコードが変更される可能性があり、その大きなネットが必要になる場合があります。

1
Phil H

この単純な違いを使用しながら使用できます。アサーションは主に実行時のデバッグ目的で使用され、仮定が検証されているかどうかを確認しますが、例外は、checked and uncheckedエラーと呼ばれる予想される予期しないエラーのチェックに使用されます。

1
SBTec

次のリンクにあるSunのドキュメントのセクション6.1.2(アサーションと他のエラーコード)を参照してください。

http://www.Oracle.com/technetwork/articles/javase/javapch06.pdf

このドキュメントは、アサーションを使用するタイミングについて私が見た中で最高のアドバイスを提供します。ドキュメントからの引用:

「良い経験則は、忘れたい例外的なケースにはアサーションを使用することです。アサーションは、必要のない状態や状態に対処し、忘れる最も早い方法です。扱う。"

1
Phil

私はあなたの質問に少し混乱していると告白します。アサーション条件が満たされない場合、例外がスローされます。紛らわしいことに、これは AssertionError と呼ばれます。 (たとえば) IllegalArgumentException のようにチェックされていないことに注意してください。これは非常によく似た状況でスローされます。

Javaでアサーションを使用する

  1. 条件/スローブロックを記述するより簡潔な手段
  2. jVMパラメータを介してこれらのチェックをオン/オフにすることができます。通常、実行時のパフォーマンスに影響するか、同様のペナルティがない限り、これらのチェックは常にオンのままにします。
1
Brian Agnew

残念ながら、アサートは無効にできます。本番環境では、予期しない何かを追跡するときに得ることができるすべての支援が必要なので、自分自身を失格と主張します。