743

Joshua Bloch は「Effective Java」で次のように述べています。

回復可能な条件にはチェック例外を使用し、プログラミング エラーには実行時例外を使用します (第 2 版の項目 58)。

これを正しく理解しているかどうか見てみましょう。

チェックされた例外についての私の理解は次のとおりです。

try{
    String userInput = //read in user input
    Long id = Long.parseLong(userInput);
}catch(NumberFormatException e){
    id = 0; //recover the situation by setting the id to 0
}

1. 上記はチェック済み例外と見なされますか?

2. RuntimeException は非チェック例外ですか?

未チェックの例外についての私の理解は次のとおりです。

try{
    File file = new File("my/file/path");
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){

//3. What should I do here?
    //Should I "throw new FileNotFoundException("File not found");"?
    //Should I log?
    //Or should I System.exit(0);?
}

4. さて、上記のコードもチェック済み例外ではないでしょうか? このような状況を回復しようとすることができますか? できますか?(注:私の3番目の質問はcatch上記の中にあります)

try{
    String filePath = //read in from user input file path
    File file = new File(filePath);
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){
    //Kindly prompt the user an error message
    //Somehow ask the user to re-enter the file path.
}

5.なぜ人々はこれを行うのですか?

public void someMethod throws Exception{

}

なぜ彼らは例外をバブルアップさせたのですか? エラー処理は早いほうがいいのではないですか? なぜ泡立つのですか?

6. 正確な例外をバブルアップするか、Exception を使用してマスクする必要がありますか?

以下は私の読書です

Java では、いつチェック済み例外を作成し、いつ実行時例外にする必要がありますか?

チェックされた例外とチェックされていない例外をいつ選択するか

4

21 に答える 21

508

多くの人が、チェックされた例外(つまり、明示的にキャッチまたは再スローする必要がある例外)はまったく使用しないでくださいと言います。たとえば、C#で削除され、ほとんどの言語にはありません。RuntimeExceptionしたがって、いつでも(チェックされていない例外)のサブクラスをスローできます

ただし、チェックされた例外は便利だと思います。APIのユーザーに、例外的な状況を処理する方法を考えさせる場合に使用されます(回復可能な場合)。チェックされた例外がJavaプラットフォームで過剰に使用されているため、人々はそれらを嫌っています。

これがこのトピックに関する私の拡張ビューです。

特定の質問について:

  1. NumberFormatException考慮はチェックされた例外ですか?
    No.NumberFormatExceptionはチェックされていません(=はのサブクラスですRuntimeException)。なんで?知らない。(しかし、方法があったはずですisValidInteger(..)

  2. RuntimeExceptionチェックされていない例外はありますか?
    はい、正確に。

  3. ここで何をすればいいですか?
    これは、このコードがどこにあり、何をしたいかによって異なります。UIレイヤーにある場合は、それをキャッチして警告を表示します。それがサービスレイヤーにある場合(まったくキャッチしないでください)、バブルさせます。例外を飲み込まないでください。ほとんどの場合に例外が発生した場合は、次のいずれかを選択する必要があります。

    • ログに記録して戻る
    • 再スローします(メソッドによってスローされることを宣言します)
    • コンストラクターで現在の例外を渡すことにより、新しい例外を作成します
  4. さて、上記のコードもチェックされた例外ではありませんか?私はこのような状況を回復することを試みることができますか?できますか?
    できたはずです。しかし、チェックされていない例外をキャッチすることを妨げるものは何もありません

  5. なぜ人々Exceptionはthrows節にクラスを追加するのですか?
    ほとんどの場合、人々は何をキャッチし、何を再スローするかを考えるのが面倒だからです。投げるExceptionことは悪い習慣であり、避けるべきです。

残念ながら、いつキャッチするか、いつ再スローするか、いつチェックされた例外を使用するか、いつチェックされていない例外を使用するかを決定できる単一のルールはありません。私はこれが多くの混乱と多くの悪いコードを引き起こすことに同意します。一般的な原則はBlochによって述べられています(あなたはその一部を引用しました)。そして、一般的な原則は、それを処理できるレイヤーに例外を再スローすることです。

于 2011-05-24T19:49:42.087 に答える
253

何かが「チェックされた例外」であるかどうかは、それをキャッチするかどうか、またはキャッチブロックで何をするかとは関係ありません。これは例外クラスのプロパティです。Exception とそのサブクラスを除いてのサブクラスであるものはすべてRuntimeException、チェックされた例外です。

Javaコンパイラは、チェックされた例外をキャッチするか、メソッドシグネチャでそれらを宣言するように強制します。プログラムの安全性を向上させるはずでしたが、大多数の意見は、それが作成する設計上の問題に値しないということのようです。

なぜ彼らは例外を泡立たせたのですか?ハンドルエラーは早ければ早いほど良いですか?なぜ泡立つのですか?

それが例外の全体的なポイントだからです。この可能性がなければ、例外は必要ありません。これらを使用すると、エラーが最初に発生した低レベルのメソッドでエラーを処理するのではなく、選択したレベルでエラーを処理できます。

于 2011-05-24T19:53:17.170 に答える
79
  1. 上記はチェック例外と見なされますか? いいえ 例外を処理しているという事実はChecked Exception、それがRuntimeException.

  2. ですか?RuntimeException_ unchecked exceptionはい

Checked Exceptionssubclasses_ java.lang.Exception Unchecked Exceptions_ subclasses_java.lang.RuntimeException

チェック済み例外をスローする呼び出しは、try{} ブロックで囲むか、メソッドの呼び出し元の上位レベルで処理する必要があります。その場合、現在のメソッドは、呼び出し元が例外を処理するための適切な調整を行うことができるように、上記の例外をスローすることを宣言する必要があります。

お役に立てれば。

Q: 正確な例外をバブルアップするか、Exception を使用してマスクする必要がありますか?

A: はい、これは非常に良い質問であり、設計上の重要な考慮事項です。クラス Exception は非常に一般的な例外クラスであり、内部の低レベルの例外をラップするために使用できます。カスタム例外を作成し、その中にラップすることをお勧めします。しかし、そして大きな 1 つ - 根底にある元の根本原因を決して曖昧にすることはありません。たとえば、Don't ever次のようにします -

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException("Cannot login!!"); //<-- Eat away original root cause, thus obscuring underlying problem.
}

代わりに次のようにします。

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException(sqle); //<-- Wrap original exception to pass on root cause upstairs!.
}

元の根本原因を食いつぶすことは、回復を超えて実際の原因を埋めることは、アプリケーション ログとエラー メッセージにしかアクセスできないプロダクション サポート チームにとって悪夢です。後者の方が優れた設計ですが、開発者が基になるメッセージを呼び出し元に渡すことができないため、多くの人はあまり使用しません。したがって、Always pass on the actual exceptionアプリケーション固有の例外にラップされているかどうかに関係なく、しっかりと注意してください。

トライキャッチについてRuntimeExceptions

RuntimeExceptions は原則として try-catch すべきではありません。通常、これらはプログラミング エラーを示しており、そのままにしておく必要があります。代わりに、プログラマーは、RuntimeException. 例:

try {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welcome to my site!);
} catch (NullPointerException npe) {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

これはプログラミングの悪い習慣です。代わりに、次のようにヌルチェックを行う必要がありました -

if (userObject != null) {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} else {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

ただし、数値の書式設定など、このようなエラーチェックが高価な場合があります。これを考慮してください-

try {
    String userAge = (String)request.getParameter("age");
    userObject.setAge(Integer.parseInt(strUserAge));
} catch (NumberFormatException npe) {
   sendError("Sorry, Age is supposed to be an Integer. Please try again.");
}

ここで、呼び出し前のエラー チェックは、本質的に parseInt() メソッド内のすべての文字列から整数への変換コードを複製することを意味し、開発者によって実装された場合にエラーが発生しやすいため、努力する価値はありません。したがって、try-catch はやめたほうがよいでしょう。

したがってNullPointerException、 とNumberFormatExceptionは両方とも、エラーを起こしやすいコードが導入される可能性を回避するために、 a を明示的にキャッチすることをお勧めしますが、 a をRuntimeExceptionsキャッチすることNullPointerExceptionは適切な null チェックに置き換える必要があります。NumberFormatException

于 2011-05-24T19:50:47.547 に答える
20

1. 例外が不明な場合は、API を確認してください。

 java.lang.Object
 extended by java.lang.Throwable
  extended by java.lang.Exception
   extended by java.lang.RuntimeException  //<-NumberFormatException is a RuntimeException  
    extended by java.lang.IllegalArgumentException
     extended by java.lang.NumberFormatException

2. はい、それを拡張するすべての例外。

3. 同じ例外をキャッチしてスローする必要はありません。この場合、新しいファイル ダイアログを表示できます。

4 . FileNotFoundExceptionすでにチェック例外です。

5. メソッド呼び出しsomeMethodで例外をキャッチすることが予想される場合は、後者をスローできます。「ボールをパスする」だけです。その使用例は、独自のプライベート メソッドでスローし、代わりにパブリック メソッドで例外を処理する場合です。

Oracle のドキュメント自体をよく読んでください: http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

設計者が、スコープ内でスローされる可能性のあるキャッチされていないすべてのチェック済み例外をメソッドに強制的に指定することを決定したのはなぜですか? メソッドによってスローされる例外はすべて、メソッドのパブリック プログラミング インターフェイスの一部です。メソッドを呼び出す人は、メソッドがスローする可能性のある例外について知っておく必要があります。これらの例外は、メソッドのパラメーターや戻り値と同様に、そのメソッドのプログラミング インターフェイスの一部です。

次の質問は、「メソッドがスローできる例外を含め、メソッドの API を文書化するのが非常に良いのであれば、実行時例外も指定しないのはなぜですか?」という質問になるかもしれません。ランタイム例外は、プログラミングの問題の結果である問題を表しており、そのため、API クライアント コードがそれらから回復したり、何らかの方法でそれらを処理したりすることは合理的に期待できません。このような問題には、ゼロ除算などの算術例外が含まれます。null 参照を介してオブジェクトにアクセスしようとするなどのポインター例外。大きすぎるか小さすぎるインデックスを介して配列要素にアクセスしようとするなど、インデックス例外。

Java 言語仕様にも重要な情報があります。

throws 句で指定されたチェック済み例外クラスは、メソッドまたはコンストラクターの実装者とユーザーの間の契約の一部です

肝心なのは、任意の をキャッチできるRuntimeExceptionということですが、必須ではなく、実際には、スローされた同じ非チェック例外を維持する必要はありません。これらは契約の一部ではないためです。

于 2011-05-24T20:03:41.627 に答える
10

1) いいえ、NumberFormatException は未チェックの例外です。チェックされていないため、キャッチしましたが(必須ではありません)。これは、 が のサブクラスである のサブクラスであるためIllegalArgumentExceptionですRuntimeException

2)RuntimeExceptionは、チェックされていないすべての例外のルートです。のすべてのサブクラスRuntimeExceptionがチェックされていません。他のすべての例外Throwableは、エラー ( の下にある) を除いてチェックされますThrowable

3/4) 存在しないファイルを選択したことをユーザーに警告し、新しいファイルを要求することができます。または、ユーザーが無効なものを入力したことをユーザーに通知するのをやめます。

5) 投げたり捕ったり'Exception'するのは悪い習慣です。しかし、より一般的には、他の例外をスローして、呼び出し元がその処理方法を決定できるようにすることができます。たとえば、ファイル入力の読み取りを処理するライブラリを作成し、メソッドに存在しないファイルが渡された場合、それを処理する方法がわかりません。発信者はもう一度質問しますか、それとも終了しますか? したがって、呼び出し元に戻ってチェーンを例外をスローします。

多くの場合、unchecked Exceptionプログラマーが入力を検証しなかったために発生NumberFormatExceptionします (最初の質問の場合)。これらの例外の生成を回避するためのより洗練された方法があるため、それらをキャッチするのはオプションです。

于 2011-05-24T19:56:40.947 に答える
8

チェックあり - 発生しやすい。コンパイル時にチェックされます。

例. FileOperations

未チェック - 不良データのため。実行時にチェックされます。

例えば..

String s = "abc";
Object o = s;
Integer i = (Integer) o;

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Sample.main(Sample.java:9)

ここでの例外は不正なデータによるものであり、コンパイル時に決定することはできません。

于 2015-07-24T16:58:37.430 に答える
6

チェック例外は、外部ライブラリを使用する開発者にとって、例外的な状況でそのライブラリのコードに問題が発生する可能性があることを思い出させる良い例だと思います。

于 2015-11-06T08:25:50.463 に答える
6

最後の質問 (他の質問は上記で完全に回答されているようです) に答えるには、「正確な例外をバブルアップする必要がありますか、それとも Exception を使用してマスクする必要がありますか?」

次のような意味だと思います。

public void myMethod() throws Exception {
    // ... something that throws FileNotFoundException ...
}

いいえ、可能な限り最も正確な例外、またはそのリストを常に宣言してください。メソッドがスローできると宣言した例外は、メソッドと呼び出し元の間の契約の一部です。スロー"FileNotFoundException"は、ファイル名が無効で、ファイルが見つからない可能性があることを意味します。呼び出し元はそれをインテリジェントに処理する必要があります。投げるExceptionということは、「おい、シットが起こる。対処する」という意味です。これは非常に悪いAPIです。

最初の記事のコメントには、" throws " が有効で合理的な宣言である例がいくつかありますが、これまでに記述した " " コードExceptionのほとんどはそうではありません。normal

于 2012-10-01T21:37:35.430 に答える
6

チェックされた例外は、コンパイル時に JVM とそれに関連するリソース (files/db/stream/socket など) によってチェックされます。チェック例外の動機は、コンパイル時にリソースが利用できない場合、アプリケーションがこれを処理するための代替動作を catch/finally ブロックで定義する必要があることです。

未チェックの例外は、純粋にプログラム上のエラーであり、間違った計算、null データ、またはビジネス ロジックの失敗でさえ実行時例外につながる可能性があります。コードで未チェックの例外を処理/キャッチすることは絶対に問題ありません。

http://coder2design.com/java-interview-questions/からの説明

于 2015-07-13T13:13:19.723 に答える
3

なぜ彼らは例外をバブルアップさせたのですか? エラー処理は早いほうがいいのではないですか? なぜ泡立つのですか?

たとえば、クライアントサーバーアプリケーションがあり、クライアントが見つけられなかったリソースを要求したか、ユーザー要求の処理中にサーバー側でエラーが発生した可能性があるとします。クライアントが要求したものを取得できなかった理由をクライアントに伝えるために、サーバーのその場合、どのようなエラーが発生したかをクライアントに通知する機会はありません。

注: 発生したエラーの種類を明確に説明するために、独自の Exception オブジェクトを作成してクライアントにスローすることができます。

于 2014-08-04T10:22:39.507 に答える
1

これらはすべてチェック済みの例外です。チェックされていない例外は、RuntimeExceptionのサブクラスです。決定はそれらをどのように処理するかではなく、コードがそれらをスローする必要があります。例外を処理していないことをコンパイラに通知させたくない場合は、チェックされていない(RuntimeExceptionのサブクラス)例外を使用します。これらは、メモリ不足エラーなど、回復できない状況のために保存する必要があります。

于 2011-05-24T19:53:43.263 に答える