コードでランタイム例外を処理することは良い習慣ではありませんか?


11

私はJavaアプリケーションで作業していますが、実行時例外は多くの場所で処理されることがわかります。例えば、

try {
    // do something
} catch(NullPointerException e) {
    return null;
}

私の質問は、いつランタイム例外を処理するのが良い習慣ですか?例外を未処理のままにする必要があるのはいつですか?


7
-1:この広く漠然とした質問に対する単一の答えはありません。このように焦点が合っていない質問に単一の回答を提供することは不可能です。この質問はひどいです。疑問のある場所の具体例を提供してください。
S.Lott

@ S.Lott頭の中に「良い」合理性がないケースだと思っているプログラマーのサブセットがあるように思えるので、このケースでは少し意見が異なります。
SoylentGray

2
@Chad:「これは「良い」合理性がない場合です」。それは本当かもしれません。しかし、唯一可能な答えは「依存する」ことです。したがって、質問には誤りがあるようです。
S.Lott

回答:


18

場合によります。

たとえば、指定された文字列を解析できない場合にInteger#parseIntスローされますNumberFormatException(RTE)。しかし、ユーザーが整数用のテキストフィールドに「x」を書き込んだからといって、アプリをクラッシュさせたくないのでしょうか。そして、最初に文字列を解析しようとしない限り、文字列を解析できるかどうかをどのようにして知るのでしょうか?したがって、この場合、RTEは単なるエラー信号であり、何らかのエラーメッセージを引き起こすはずです。これチェック済みの例外であるべきだと主張することもできますが、何ができるのか-そうではありません。


2
「それは依存します」に同意しますが、あなたの構文解析の例は、API設計が悪い場合のようです。Integer#parseInt実際にMaybe<Integer>代わりにa を返し、例外をまったくスローしないでください。
ヨルグWミットタグ

3
@JörgW Mittag:それは悪いAPIデザインであることに同意しますが、私たちが対処しなければならない現実の世界です。適切スロー可能オブジェクト/戻り値を処理する方法世界がどのように依存して、実際にはない、それは最適な方法については、働くべきで仕事:-)
Joonas Pulakka

ここでのポイントは、予想される条件(整数ではなくユーザー入力)に対して意味のある何かを行うことができるということです。NPEを飲み込むだけではスタイルが悪く、既存のプログラミングエラーを隠してしまうだけです。
ユルゲンストロベル

7

NullPointerExceptionsは通常、欠落したnullチェックの兆候です。したがって、このようにキャッチする代わりに、適切なnullチェックを追加して、例外がスローされないようにする必要があります。

ただし、RunTimeExceptionsを処理することが適切な場合もあります。たとえば、コードを変更して適切な場所にnullチェックを追加できない場合、または例外がNullPointerException以外の場合です。

例外処理のあなたの例はひどいです。そうすると、スタックトレースと問題に関する正確な情報が失われます。また、実際には別の場所で別のNullPointerExceptionをトリガーし、何が起こったのか、それを解決する方法について誤解を招く情報を取得するため、実際には解決していません。


1
NULLチェックはパフォーマンス面でより良い決定であると付け加えたいと思います。
マフムードホッサム

...まだ、1箇所で「失敗することのない」多数の割り当てを行っている場合、それぞれにnullチェックを追加すると、コードが途方もなく難読化される可能性があります。キャッチオール例外(だけでなく、状況を適切に処理しreturn null;ます)がより良いソリューションです。
SF。

おそらく、javaと他の何かを混同しているでしょう(例:C ++)。割り当てが失敗すると、OutOfMemoryErrorまたは同様のエラーが発生しますが、nullポインターは発生しません。例外の代わりにnullリターンを非表示にすることは、コードが他の場所で爆発するのを待っているエラーを非表示にすることです。
deadalnix

newstd::bad_allocC ++をスローします。
R.マルティーニ・フェルナンデス

new演算子がオーバーロードしていないと仮定すると、これは一般的な慣行です。C ++では、何でも起こります;)しかし、OK、Cのmallocとしましょう。重要な点は、Javaでは決して得られなかったことです。
deadalnix

4

予想される例外を予想どおりに処理します。(DB読み取り/書き込みエラーと同様)。予期しない例外が発生しました。他のどこかが例外を予期していて、そのロジックを持っているかもしれません。


2

例外はそれだけです。例外。例外を使用する際のベストプラクティスは、例外を使用して、発生することが予想されるものとは逆の状況が発生する状況をカバーすることです。典型的な例は、ファイルが存在しない場合にスローされるFileNotFoundExceptionです。ファイルの存在をテストしている場合は、File.exists()を使用します。これは、何かを打ったかどうかを確認するために10フィートのスティックを突き刺しているだけだからです。

try catchで囲み、存在するかのようにファイルを使用することで技術的に同じ結果を得ることができますが、A)例外は一般にリソース的にコストがかかり、B)存在する場合はファイルが存在することをプログラマが想定しますプログラムの全体的な混乱を増すtry catchで。

データベースから値を取得するメソッドを作成する状況は数多くあります。千の事柄がうまくいかない可能性があり、必要な情報が1つだけであるため、5つのさまざまな例外を含むtry catchリストで呼び出しを囲むのは不便です。したがって、fetchメソッドで例外をキャッチします。何か問題が発生した場合は、適切なアクションを実行して、データベース接続を閉じるか、finally節のwhatnotでnullを返します。これは、コードを簡素化するだけでなく、「null」が例外から取得したメッセージと同じメッセージを送信するためです。fetchメソッドで例外の詳細を管理しますが、物事が起こらないときはどうするかを管理します

例えば:

Integer getUserCount() {
   Integer result = null;
   try {
      // Attempt to open database and retrieve data
   } catch (TimeoutException e) {
      logger.error("Got a watch?");
   } catch (MissingDatabaseException e) {
      logger.error("What are you smoking?");
   } catch (PermissionsToReadException e) {
      logger.error("Did you *really* think you were getting away with that?");
   } catch (PressedSendButtonToHardException e) {
      logger.error("Seriously.. just back away from the computer... slowly..");
   } catch (WTFException e) {
      logger.error("You're on your own with this one.. I don't even know what happened..");
   } finally {
      // Close connections and whatnot
   }
   return result;
}

void doStuff() {
   Integer result = getUserCount();
   if(result != null) {
       // Went as planned..
   }
}

6
File.exists()を使用して結果に依存している場合、File.exists()とFile.open()の間でファイルが削除されると競合状態が発生する可能性があります。これがセキュリティ上重要なバグを引き起こす場合、攻撃者は故意にこの状態を引き起こす可能性があります。このため、操作をアトミックに保つ方がよい場合があります。つまり、試して例外をキャッチします。
user281377

1
また、アプリケーションの実行に必要なファイルがあります。それらは例外的な条件です。アプリケーションが機能するために必要なファイルがある場合、そのファイルから読み取って例外的なケースの例外を処理しない理由はありません。意図がより明確になると思います。
トーマスオーエンズ

これは、nullを返すという悪い決定です。ある時点でNullPointerExceptionが発生し、問題のデバッグが非常に困難になります。誰かがある時点でヌルチェックを忘れるからです。
deadalnix

@deadalnix:そうでなければ、try-catchで囲むことを簡単に忘れることができると主張できます。違いは機能ではなくスタイルの問題です。
ニール

@ammoQ:私は同意しません。File.exists()を使用する必要があり、使用する前に削除されるというまれな状況では、例外は適切です。違いは、キャッチをどこで保持するかです。ログに記録して報告するために、予期しないエラーに対する包括的な例外キャッチャーを用意するだけです。
ニール

-5

はい、実行時例外を正しく処理することはお勧めできません。理由は、コストとメモリの消費が大きいと考えられるためです。


5
こんにちは、あなたは答えを詳しく説明できますか?事実、参考文献、または経験に裏打ちされていないワンライナーは、あまり役に立ちません。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.