Javaでのチェック済み例外とチェックなし例外の理解


703

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.正確な例外をバブルアップするか、または例外を使用してマスクする必要がありますか?

以下は私の読みです

Javaでは、いつチェック例外を作成する必要があり、いつランタイム例外にする必要がありますか?

チェックされた例外とチェックされていない例外を選択するタイミング


6
未チェックの例外の良い例があります。DataSeries常に時間ベースの順序で保持する必要があるデータを保持するクラスがあります。DataPointの末尾にを追加するメソッドがありDataSeriesます。すべてのコードがプロジェクト全体で正しく機能している場合は、DataPointすでに最後にある日付より前の日付を持つを最後に追加しないでください。プロジェクト全体のすべてのモジュールは、この自明で構築されています。ただし、この状態をチェックし、それが発生した場合はチェックされない例外をスローします。どうして?それが起こった場合、私は誰がこれをやっているかを知り、それを修正したいと思います。
エリックロバートソン、

3
さらに混乱を追加します。多くの人が約10年前にチェック例外を提唱していましたが、今日の見方はますます「チェック例外は悪い」に向かっています。(しかし、私はそれには同意しません)
Kaj

10
これは、例外を処理するのに役立つ何かがある場合にのみ例外を処理するのに役立ちます。それ以外の場合は、呼び出し元に例外を処理させる必要があります。ログに記録して、発生しなかったふりをしても、通常は役に立ちません。投げ直すだけでは意味がありません。RuntimeExceptionでラップすることは、一部の人が考えるほど有用ではありません。コンパイラーがユーザーを支援しなくなるだけです。(私見)
ピーター・ローリー、

40
チェック付き/チェックなしの例外について、誤解を招くような用語の使用を停止する必要があります。彼らは呼ばれるべきチェック義務付けチェックによって義務付けられていない例外。
Blessed Geek 14年

3
私はまた、abt ur 5番目のポイントpublic void method_nameが例外をスローすることを考えました{}一部の人々はなぜそうするのですか?
Mavenのツ

回答:


474

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

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

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

特定の質問に関しては:

  1. NumberFormatExceptionチェック済み例外と見なされますか?
    番号NumberFormatExceptionはチェックされていません(=はのサブクラスですRuntimeException)。どうして?知りません。(しかし、メソッドがあったはずですisValidInteger(..)

  2. RuntimeExceptionチェックされない例外?
    はい、正確に。

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

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

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

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


36
例外のスローに関しては、人々が怠惰だからとは限りません。フレームワークを実装するときに、フレームワークのユーザーが例外をスローできるようにすることも一般的です。たとえば、JSEでCallableインターフェースの署名をチェックできます
Kaj

10
@Kaj-はい、Callable、インターセプターなどの一般的なものは特別なケースです。しかし、ほとんどの場合それは人々が怠惰だからです:)
Bozho

7
re:3.1「ログに記録して戻る」慎重に行ってください。これは食べるか隠すか、例外に非常に近いです。私は問題を示さない何かのためにこれをします、それは本当に例外ではありません。ログが氾濫し、無視されやすくなります。
クリス、

4
「APIのユーザーに例外的な状況への対処方法を考えさせたい場合」-望まないかどうかを誰かに考えさせることはできません。彼らが考えたくない場合、彼らはまったく何もしないか、悪いことに、重大なエラー情報を削除または干渉する、貧弱な例外ブロックを書き込みます。これが、チェックされた例外が失敗する理由です。
adrianos 2012

3
@adrianos「...あなたが誰も望まないなら、あなたに誰かに強制することはできません...」何度も何度も議論は、それでもチェックされた例外を失敗としてラベル付けするための最も悪い説明であることがわかります。余談ですが、私はコンパイル(および実行時エラーも同様に)が事実上設計によって事実上不可能にされたそのような言語を見てきました。その道はいくつかの非常に暗い場所につながりました。
2016

233

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

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

なぜ彼らは例外が浮上するのですか?エラーを処理しないのは早いほど良いですか?なぜ泡立ちますか?

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


3
ありがとうございました!私は時々クレープアウト原理のがらくたのために私のメソッドから例外を投げます。私のチームの開発者の1人が、例外を処理するために無効なxpath式を入力したいと考えています。万が一の場合、彼らは例外をキャッチし、コードレビューでそれについて聞いて何もしません。
jeremyjjbrown

12
「RuntimeExceptionとそのサブクラスを除いて、Throwableのサブクラスであるものはすべてチェック例外です。」-記述が間違っています。エラーはThrowableも継承し、チェックされていません。
Bartzilla

8
@JonasEicher:基本的に、例外の主な利点は、コールスタックのどこでエラーを処理するかを選択できることです。多くの場合、非常に高いレベルにあり、エラー処理のアーティファクトがまったくないレイヤーを維持します。チェックされた例外は、まさにその利点を破壊します。別の問題は、チェック済み/未チェックの区別が、例外の概念的な分類を表す例外クラスに関連付けられていることです。これは、必ずしもまったく関連しない2つの側面が混在していることです。
Michael Borgwardt 2013年

2
「しかし、大多数の意見は、それが生み出す設計上の問題に値するものではないようだ」-引用してください?
ケルビン2015年

3
@Bartzillaはい。完全を期すために、JavadocがThrowable言っているように、「ThrowableおよびThrowableのサブクラスではなく、RuntimeExceptionまたはErrorのサブクラスでもないものは、チェック済み例外と見なされます」
Bart van Heukelom

74
  1. 上記はチェック例外と見なされますか?あなたが例外を処理しているという事実は、それがありませんありませんChecked Exception、それがある場合RuntimeException

  2. ありますか?はいRuntimeExceptionunchecked exception

Checked Exceptionsあるsubclassesjava.lang.Exception Unchecked Exceptionsですsubclassesjava.lang.RuntimeException

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

お役に立てれば。

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

A:はい、これは非常に良い質問であり、重要な設計上の考慮事項です。Exceptionクラスは非常に一般的な例外クラスであり、内部の低レベルの例外をラップするために使用できます。カスタム例外を作成して、その中にラップする方がよいでしょう。しかし、そして大きな問題です-根本的な根本原因を曖昧にすることは決してありません。例として、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

RuntimeException■原則として、試行錯誤してはなりません。これらは一般にプログラミングエラーを通知するため、そのままにしておく必要があります。代わりに、プログラマは、結果としてになる可能性のあるコードを呼び出す前に、エラー状態を確認する必要がありますRuntimeException。例:

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

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

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を廃止することをお勧めします。

したがってNullPointerExceptionNumberFormatException両方ともRuntimeExceptions、エラーを起こしやすいコードが導入される可能性を回避するために明示的にNullPointerExceptionキャッチすることをお勧めしNumberFormatExceptionます。


ありがとうございました。をバブリングするときのもう1つの質問exceptionは、正確な例外をバブリングするか、を使用してマスクするかExceptionです。私はいくつかのレガシーコードの上にコードを書いExceptionていて、あちこちで泡立っています。これは正しい動作ですか?
タンファン

1
これは非常に良い重要な質問です。私の回答を編集して説明を含めました。
d-live

どうもありがとうございました。内容を教えてもらえLoginFailureException(sqle)ますか?
タンファン

1
私はそのようなもののためのコードを持っていません、私は名前などをクックアップしました。java.lang.Exceptionが表示された場合、4つのコンストラクターがあり、そのうちの2つはjava.lang.Throwableを受け入れます。上記のスニペットでLoginFailureExceptionException、拡張とコンストラクターの宣言を想定していたpublic LoginFailureException(Throwable cause) { super(cause) }
d-live

トピックに関する最良の回答。実行時例外は、適切なプログラミングの欠如が原因で発生するため、キャッチすべきではないと思います。「元の根本原因の埋没を食い止めて、回復を超えた実際の原因を取り除くことは、アプリケーションログとエラーメッセージだけにアクセス権が与えられる本番サポートチームにとって悪夢です。」という部分に完全に同意します。
フセイン2016

19

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、しかし、あなたがする必要はありませんと、それらが契約の一部ではないとして、実際に実装は、スロー同じ非チェック例外を維持するために必要とされていません。


ありがとうございました。をバブリングするときのもう1つの質問exceptionは、正確な例外をバブリングするか、を使用してマスクするかExceptionです。私はいくつかのレガシーコードの上にコードを書いExceptionていて、あちこちで泡立っています。これは正しい動作ですか?
タンファム

1
:私は私はそれに答えるよりも、より多くの知識を持つ人々をできるようになる@Harry stackoverflow.com/questions/409563/...
Aleadam

10

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

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

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

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

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


ありがとうございました。をバブリングするときのもう1つの質問exceptionは、正確な例外をバブリングするか、を使用してマスクするかExceptionです。私はいくつかのレガシーコードの上にコードを書いExceptionていて、あちこちで泡立っています。これは正しい動作ですか?
タンファム

メソッドに例外をスローさせることもできます(これは理想的ではありません)。または、例外をキャッチして、より適切な例外(IOExceptionなど)をスローします。すべての例外は、コンストラクター内の例外を「原因」として受け取る可能性があるため、それを使用する必要があります。
dontocsata

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)

ここでの例外は不良データが原因であり、コンパイル時にそれを特定することはできません。


6

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

チェックされていない例外は、純粋にプログラム上のエラー、誤った計算、nullデータ、またはビジネスロジックの障害でさえ、ランタイム例外につながる可能性があります。コード内のチェックされていない例外を処理/キャッチすることは絶対に問題ありません。

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


5

チェックされていない例外とチェックされた例外の違いについての私のお気に入りの説明は、Javaチュートリアルのトレイル記事「チェックされていない例外-論争」(この投稿ですべての初歩を取得して申し訳ありませんが、ねえ、基本は時々最高です)によって提供されます。

要点のガイドラインは次のとおりです。クライアントが例外からの回復が合理的に期待できる場合は、チェックされた例外にします。クライアントが例外から回復するために何もできない場合は、チェックされていない例外にします

「スローする例外のタイプ」の核心は(ある程度)セマンティックであり、上記の引用は優れたガイドラインを提供します(したがって、C#がチェックされた例外を取り除いたという概念に私はまだ驚いています-特にLiskovが主張するように)それらの有用性)。

残りは論理的になります。コンパイラはどの例外に対して明示的に応答することを期待していますか?クライアントが回復すると予想されるもの。


5

最後の質問に答えるには(他の人は上で完全に回答しているように見えます)、「正確な例外を泡立たせるか、例外を使用してマスクする必要がありますか?」

私はあなたがこのようなものを意味すると仮定しています:

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

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

最初の記事のコメントには、「throws Exception」が有効で妥当な宣言であるいくつかの例がありnormalますが、これは、これから作成するほとんどの「」コードには当てはまりません。


正確には、チェック例外宣言をコードドキュメントの一部にし、ソフトウェアの使用者を支援します。
サルバドールバレンシア

5

ランタイム例外:ランタイム例外は、チェックされていない例外と呼ばれます。他のすべての例外はチェック例外であり、java.lang.RuntimeExceptionから派生しません。

チェック例外チェック例外は、コードのどこかでキャッチする必要があります。チェックされた例外をスローするメソッドを呼び出しても、チェックされた例外をどこかでキャッチしない場合、コードはコンパイルされません。これがチェック例外と呼ばれる理由です。コンパイラは、それらが処理または宣言されていることを確認してチェックします。

Java APIのいくつかのメソッドはチェック済み例外をスローするため、自分で記述していないメソッドによって生成された例外に対処するために、例外ハンドラーを作成することがよくあります。


3

なぜ彼らは例外が浮上するのですか?エラーをより早く処理しないのですか?なぜ泡立ちますか?

たとえば、クライアントサーバーアプリケーションがあり、クライアントが見つけられなかったリソースまたは何か他のエラーを要求したとします。ユーザー要求の処理中にサーバー側で発生した可能性があるエラーの場合、それが義務です。サーバー側でクライアントが要求したものを取得できなかった理由をクライアントに通知するため、サーバー側でそれを達成するために、飲み込んだり処理したりする代わりに、throwキーワードを使用して例外をスローするようにコードが記述されます。その場合、どのエラーが発生したかをクライアントに知らせる機会はありません。

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


いい視点ね。これは、ロジックフローを制御し、アプリケーションのビジネスロジックを監視する、最も責任のある最上層までバブルすることを意味します。たとえば、重要な何かが欠けている、または応答しないことをデータベースレイヤーがクライアントに通知することは不可能です。最上位のサーバーレイヤーに達すると、重大なエラーメッセージでクライアントのビューを更新するのが簡単になります。
サルバドールバレンシア


3

チェックされた例外をまったく使用しない理由を追加したいだけです。これは完全な答えではありませんが、あなたの質問の一部を解決し、他の多くの答えを補完すると思います。

チェックされた例外が関係するときはいつでもthrows CheckedException、メソッドシグネチャのどこかにあります(CheckedExceptionチェックされた例外である可能性があります)。シグネチャは例外をスローしません。例外のスローは実装の一側面です。インターフェース、メソッドシグネチャ、親クラス、これらすべてのものは、それらの実装に依存するべきではありません。ここでチェックされた例外の使用法(実際throwsにはメソッドシグネチャでを宣言する必要があるという事実)は、上位レベルのインターフェイスをこれらのインターフェイスの実装にバインドしています。

例を挙げましょう。

このような素敵でクリーンなインターフェースを作ってみましょう

public interface IFoo {
    public void foo();
}

foo()次のように、methodの多くの実装を書くことができます

public class Foo implements IFoo {
    @Override
    public void foo() {
        System.out.println("I don't throw and exception");
    }
}

クラスフーは完全に元気です。それではクラスバーで最初の試みをしましょう

public class Bar implements IFoo {
    @Override
    public void foo() {
        //I'm using InterruptedExcepton because you probably heard about it somewhere. It's a checked exception. Any checked exception will work the same.
        throw new InterruptedException();
    }
}

このクラスバーはコンパイルされません。InterruptedExceptionはチェックされた例外であるため、(メソッドfoo()内でtry-catchを使用して)キャプチャするか、それをスローすることを宣言する(throws InterruptedExceptionメソッドシグネチャに追加する)必要があります。ここでこの例外をキャプチャしたくないので(他の場所で適切に処理できるように上方向に伝播させたい)、シグネチャを変更しましょう。

public class Bar implements IFoo {
    @Override
    public void foo() throws InterruptedException {
        throw new InterruptedException();
    }
}

このクラスバーもコンパイルされません!署名が異なるため、Barのメソッドfoo()はIFooのメソッドfoo()をオーバーライドしません。@Overrideアノテーションを削除することもできますが、IFooのようなインターフェイスに対してプログラムを作成し、IFoo foo;後で、使用する実装を決定したいと思いfoo = new Bar();ます。Barのメソッドfoo()がIFooのメソッドfooをオーバーライドしない場合、foo.foo();それを実行しても、Barのfoo()の実装は呼び出されません。

バーのpublic void foo() throws InterruptedExceptionオーバーライドIFoo を作成するpublic void foo()にはthrows InterruptedException、IFooのメソッドシグネチャに追加する必要があります。ただし、これはfoo()メソッドのシグネチャがIFooのメソッドシグネチャとは異なるため、Fooクラスで問題を引き起こします。さらに、throws InterruptedExceptionFooのメソッドfoo()に追加した場合、Fooのメソッドfoo()が、InterruptedExceptionをスローするが、InterruptedExceptionをスローしないことを宣言していることを示す別のエラーが発生します。

ご覧のとおり(私がこのことを説明するのにまともな仕事をした場合)、InterruptedExceptionのようなチェック例外をスローしているという事実は、インターフェイスIFooをその実装の1つに結び付けることを強制し、それがIFooに混乱を引き起こします。他の実装!

これは、チェックされた例外が悪い理由の1つです。キャップ。

1つの解決策は、チェックされた例外をキャプチャし、チェックされていない例外にラップして、チェックされていない例外をスローすることです。


2
はい、あなたはそれを捕らえたくないと言ったので、それは悪いです。しかし、IFOOの署名に影響を与えないようにするには、そうする必要があります。例外をキャッチしないようにするために、すべてのインターフェイスシグネチャを再調整するのではなく、それを実行します(例外が悪いためだけです)。
サルバドールバレンシア

ええ、同意します。私は何かについて少し不明瞭でした。例外を伝播させたいので、どこか別の場所で処理できます。1つの解決策は、InterruptedExceptionをキャッチし、チェックされていない例外をスローすることです。つまり、チェックされた例外を回避し、チェックされていない例外を(ラッパーとしてのみ意味がある場合でも)
渡す

「しかし、これはfoo()メソッドのシグネチャがIFooのメソッドシグネチャと異なるため、私のFooクラスで問題を引き起こします。」私はあなたのアイデアをテストthrows InterruptedExceptionしました。IFooのメソッドシグネチャに追加しても、何の実装でも何もスローせずにコンパイルすることが可能です。そのため、実際には問題は発生しません。インターフェイスですべてのメソッドシグネチャをthrow Exceptionにした場合、それは実装に例外をスローするかどうかを選択するだけです(すべての例外をExceptionカプセル化するなど、すべての例外)。
Flyout91 2018

ただし、そのようなインターフェースを実装して「未実装のメソッドを追加」などをクリックするとthrow Exception、実装が何もスローしないか、またはより具体的な例外。しかし、インターフェイスのメソッドに対して常に例外をスローすることは良い習慣であると私はまだ感じています。これも、ユーザーに何かをスローするかしないかを選択できるためです。
Flyout91 2018

これは全体のポイントを逃しています。インターフェースの目的は、クライアントが満たす必要のある契約を宣言することです。これには、処理可能な障害シナリオが含まれる場合があります。実装でエラーが発生した場合、そのエラーを、クライアントインターフェイスによって宣言された適切な抽象エラーにマップする必要があります。
エリクソン2018

3
  • Javaは、例外の2つのカテゴリー(チェックありとチェックなし)を区別します。
  • Javaは、チェック例外のキャッチまたは宣言された要件を適用します。
  • 例外のタイプは、例外をチェックするかどうかを決定します。
  • subclassesクラスの直接的または間接的なすべての例外タイプRuntimeException は、チェックされていない例外です。
  • クラスから継承するが、クラスから継承しExceptionないすべてのクラスRuntimeExceptionは、と見なされますchecked exceptions
  • クラスErrorから継承するクラスは、チェックされていないと見なされます。
  • コンパイラは、各メソッドの呼び出しと減速をチェックして、メソッドがスローするかどうかを判断しchecked exceptionます。
    • その場合、コンパイラーは例外が確実にキャッチされるか、throws節で宣言されるようにします。
  • catch-or-declare要件のdeclare部分を満たすには、例外を生成するメソッドがthrowsを含む句を提供する必要がありますchecked-exception
  • Exception クラスは、キャッチまたは宣言するのに十分重要であると見なされたときにチェックされるように定義されます。

2

これは、決定に役立つ簡単なルールです。これは、Javaでのインターフェースの使用方法に関連しています。

あなたのクラスを取り、インターフェイスがクラスの機能を記述するが、(インターフェイスがそうであるように)基礎となる実装のどれも記述しないように、そのインターフェイスを設計することを想像してください。おそらく、別の方法でクラスを実装する可能性があると仮定します。

インターフェースのメソッドを見て、それらがスローする可能性のある例外を検討します。

例外がメソッドによってスローされる可能性がある場合、基礎となる実装に関係なく(つまり、機能のみを説明している場合)、インターフェイスのチェックされた例外である可能性があります。

基礎となる実装が原因で例外が発生した場合、それはインターフェースに存在してはなりません。したがって、それはクラスのチェックされていない例外であるか(チェックされていない例外はインターフェイスシグネチャに表示される必要がないため)、それをラップして、インターフェイスメソッドの一部であるチェックされた例外として再スローする必要があります。

ラップして再スローする必要があるかどうかを判断するには、インターフェイスのユーザーが例外条件をすぐに処理する必要があるのが理にかなっているのか、または例外が一般的すぎて何もすることができず、それを実行する必要があるのか​​を再度検討する必要がありますスタックを伝播します。ラップされた例外は、定義している新しいインターフェイスの機能として表現される場合に意味がありますか、それとも、他のメソッドでも発生する可能性のあるエラー状態のバッグの単なるキャリアですか?前者の場合、それはまだチェック済み例外である可能性があり、そうでない場合はチェック解除する必要があります。

通常、「バブルアップ」例外(キャッチアンドスロー)を計画する必要はありません。例外は、呼び出し元によって処理されるか(この場合はチェックされます)、または高レベルのハンドラーに到達する必要があります(この場合、チェックされていない場合が最も簡単です)。


2

コードでチェックされた例外をスローし、catchが数レベル上にある場合、あなたとcatchの間の各メソッドのシグネチャで例外を宣言する必要があることを指摘するだけです。したがって、throwのパスにあるすべての関数は、その例外の詳細を認識している必要があるため、カプセル化は壊れています。


2

つまり、上記のモジュールが実行時に処理することになっている例外は、チェック例外と呼ばれます。その他は、RuntimeExceptionまたはのチェックされていない例外Errorです。

このビデオでは、Javaのチェックされた例外とチェックされていない例外について説明しています:https :
//www.youtube.com/watch?v=ue2pOqLaArw


1

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


ええと。NumberFormatExceptionがチェック例外である場合、あなたが言うように、それがRuntimeExceptionから継承されているという事実と矛盾していませんか?
eis

すみません、よくわかりませんでした。NumberFormatExceptionではなく、FileNotFoundExceptionを参照していました。彼の#2と#4に基づいて、チェックされているかチェックされていないかは、例外をキャッチした後の処理方法に基づいていると思われたようです。それがどのように定義されたかではありません。
2012

-1

チェックされた例外を嫌う別の証拠を誰かが気にかけている場合は、人気のあるJSONライブラリの最初の数段落を参照してください。

「これはチェックされた例外ですが、ほとんど回復できません。ほとんどの呼び出し元は、この例外をチェックされていない例外にラップして再スローするだけです。」

では、代わりに「単純にそれをラップする」べきなら、なぜ誰もが開発者に例外をチェックさせ続けるのはなぜでしょうか?笑

http://developer.android.com/reference/org/json/JSONException.html


4
ラップして再スローする必要があるのは、ほとんどの呼び出し元だけであり、すべての呼び出し元ではありません。例外がチェックされるという事実は、呼び出し元が「ほとんどの」呼び出し元の1つであるか、または例外を処理できる、または処理する必要のある少数派の1つであるかを考慮する必要があることを意味します。
ウォーレンデュー

1
呼び出しごとにエラーをチェックする場合は、Cに「戻って」ください。例外は、コードを汚染することなく、通常のプログラムの実行を異常から分離する方法です。例外により、あるレベルでエラーを無視することはできません。
Slawomir、2014年

-1

チェックされた例外

  • 実行時にプログラムがスムーズに実行されるようにコンパイラーによってチェックされる例外は、チェック例外と呼ばれます。

  • これらはコンパイル時に発生します。

  • これらが適切に処理されない場合、コンパイル時エラー(例外ではない)が発生します。
  • RuntimeExceptionを除くExceptionクラスのすべてのサブクラスは、チェック済み例外です。

    仮説の例 -家を出て試験に出かけるとしますが、自宅でホールチケットを受け取ったかどうかを確認すると(コンパイル時)、試験ホールでは問題は発生しません(実行時)。

未チェックの例外

  • コンパイラによってチェックされない例外は、チェックされない例外と呼ばれます。

  • これらは実行時に発生します。

  • これらの例外が適切に処理されない場合、コンパイル時エラーは発生しません。ただし、プログラムは実行時に途中で終了します。

  • RunTimeExceptionおよびErrorのすべてのサブクラスは、チェックされない例外です。

    仮説の例 -あなたが試験会場にいるが、どういうわけかあなたの学校は火災事故(実行時の手段)を起こしていて、その時点では何もできず、事前に(コンパイル時に)予防策をとることができるとします。


-2

すべての例外は、チェックされた例外でなければなりません。

  1. 未チェックの例外は無制限のgotoです。そして、無制限のゴトは悪いものと考えられています。

  2. 未チェックの例外はカプセル化を壊します。これらを正しく処理するには、スローアーとキャッチャーの間の呼び出しツリー内のすべての関数が、バグを回避するために認識されている必要があります。

  3. 例外は、例外をスローする関数のエラーですが、それらを処理する関数のエラーではありません。例外の目的は、プログラムがエラーであるかどうかの決定を別のコンテキストに遅らせることにより、プログラムにもう一度チャンスを与えることです。正しい判断を下せるのは、他の状況でのみです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.