捕まえるのは悪い習慣Throwable
ですか?
たとえば、次のようなものです。
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
これは悪い習慣ですか、それともできるだけ具体的にする必要がありますか?
捕まえるのは悪い習慣Throwable
ですか?
たとえば、次のようなものです。
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
これは悪い習慣ですか、それともできるだけ具体的にする必要がありますか?
できるだけ具体的にする必要があります。そうしないと、予期しないバグがこのように忍び寄る可能性があります。
その上、Throwable
カバーError
も同様であり、それは通常、戻りのポイントではありません。あなたはそれを捕まえたり処理したりしたくはありません、あなたはあなたがそれを適切に修正することができるようにあなたのプログラムをすぐに死なせたいです。
これは悪い考えです。実際、捕まえることさえException
通常悪い考えです。例を考えてみましょう:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(Throwable e) {
inputNumber = 10; //Default, user did not enter valid number
}
ここで、getUserInput()がしばらくブロックし、別のスレッドがスレッドを可能な限り最悪の方法で停止するとします(thread.stop()を呼び出します)。キャッチブロックはThreadDeath
エラーをキャッチします。これは非常に悪いです。その例外をキャッチした後のコードの動作は、ほとんど定義されていません。
例外のキャッチでも同様の問題が発生します。おそらくgetUserInput()
、InterruptException、結果をログに記録しようとしているときに許可が拒否された例外、またはその他のあらゆる種類の失敗が原因で失敗しました。何が悪かったのかわからないので、問題を解決する方法もわかりません。
3つのより良いオプションがあります:
1-処理方法を知っている例外を正確にキャッチします。
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(ParseException e) {
inputNumber = 10; //Default, user did not enter valid number
}
2-発生した例外を再スローし、処理方法がわからない場合:
try {
doSomethingMysterious();
} catch(Exception e) {
log.error("Oh man, something bad and mysterious happened",e);
throw e;
}
3--finallyブロックを使用して、再スローすることを覚えておく必要がないようにします。
Resources r = null;
try {
r = allocateSomeResources();
doSomething(r);
} finally {
if(r!=null) cleanUpResources(r);
}
また、捕まえると、特別な扱いが必要なThrowable
捕まえることもありますのでご注意ください。InterruptedException
詳細については、InterruptedExceptionの処理を参照してください。
チェックされていない例外のみをキャッチしたい場合は、このパターンも検討してください。
try {
...
} catch (RuntimeException exception) {
//do something
} catch (Error error) {
//do something
}
このように、コードを変更し、チェックされた例外をスローできるメソッド呼び出しを追加すると、コンパイラーはそのことを通知し、この場合の対処方法を決定できます。
Errorクラスのjavadocから直接(これらをキャッチしないことをお勧めします):
* An <code>Error</code> is a subclass of <code>Throwable</code>
* that indicates serious problems that a reasonable application
* should not try to catch. Most such errors are abnormal conditions.
* The <code>ThreadDeath</code> error, though a "normal" condition,
* is also a subclass of <code>Error</code> because most applications
* should not try to catch it.
* A method is not required to declare in its <code>throws</code>
* clause any subclasses of <code>Error</code> that might be thrown
* during the execution of the method but not caught, since these
* errors are abnormal conditions that should never occur.
*
* @author Frank Yellin
* @version %I%, %G%
* @see java.lang.ThreadDeath
* @since JDK1.0
メソッドから例外バブルを完全に発生させることができない場合は、悪い習慣ではありません。
本当に例外を処理できない場合は、悪い習慣です。メソッドシグネチャに「スロー」を追加する方が、キャッチして再スローするよりも、さらに悪いことに、RuntimeExceptionでラップして再スローするよりも優れています。
エラーを過度にスローするライブラリを使用している場合は、Throwableをキャッチする必要があります。そうしないと、ライブラリがアプリケーションを強制終了する可能性があります。
ただし、このような状況では、すべてのThrowableではなく、ライブラリによってスローされた特定のエラーのみを指定するのが最適です。
Throwableは、(例外だけでなく)スローできるすべてのクラスの基本クラスです。OutOfMemoryErrorまたはKernelErrorをキャッチした場合にできることはほとんどありません(java.lang.Errorをキャッチするタイミングを参照してください) 。
例外をキャッチするだけで十分です。
質問は少し曖昧です。Throwable
「捕まえても大丈夫ですか」、「捕まえThrowable
て何もしなくても大丈夫ですか」と聞いていますか?ここの多くの人々は後者に答えました、しかしそれは副次的な問題です。99%の確率で、キャッチしているかどうかに関係なく、例外を「消費」したり破棄したりしないでThrowable
くださいIOException
。
例外を伝播する場合、答えは(非常に多くの質問に対する答えのように)「状況によって異なります」です。それはあなたが例外を除いて何をしているのか、なぜあなたがそれを捕まえているのかによります。
キャッチしたい理由の良い例Throwable
は、エラーが発生した場合に何らかのクリーンアップを提供することです。たとえば、JDBCでは、トランザクション中にエラーが発生した場合、トランザクションをロールバックする必要があります。
try {
…
} catch(final Throwable throwable) {
connection.rollback();
throw throwable;
}
例外は破棄されず、伝播されることに注意してください。
しかし、一般的なポリシーとして、理由がなく、どの特定の例外がスローされているかを確認するのが面倒であるためにキャッチThrowable
することは、形式が悪く、悪い考えです。
それはあなたの論理に依存するか、あなたのオプション/可能性にもっと具体的になります。意味のある方法で対応できる可能性のある特定の例外がある場合は、最初にそれをキャッチして実行できます。
存在せず、すべての例外とエラーに対して同じことを行うと確信している場合(たとえば、エラーメッセージで終了する)、スロー可能なものをキャッチすることは問題ありません。
通常、最初のケースが成り立ち、スローアブルを捕まえることはできません。しかし、それを捕まえることがうまくいく場合はまだたくさんあります。
非常に悪い習慣として説明されていますが、それが有用であるだけでなく必須であるというまれなケースを見つけることがあります。これが2つの例です。
意味のある完全なエラーページをユーザーに表示する必要があるWebアプリケーション。このコードは、try/catch
すべてのリクエストハンデラー(サーブレット、ストラットアクション、または任意のコントローラー...)の周りで大きいため、これが発生することを確認します。
try{
//run the code which handles user request.
}catch(Throwable ex){
LOG.error("Exception was thrown: {}", ex);
//redirect request to a error page.
}
}
別の例として、送金ビジネスを提供するサービスクラスがあるとします。このメソッドは、TransferReceipt
転送が完了した場合、または転送NULL
できなかった場合にを返します。
String FoundtransferService.doTransfer( fundtransferVO);
List
これで、ユーザーからの送金を画像化できます。これらすべてを行うには、上記のサービスを使用する必要があります。
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}
しかし、例外が発生した場合はどうなりますか?1つの転送が成功した場合と失敗した場合があるため、停止しないでください。すべてのユーザーを続行しList
、各転送に結果を表示する必要があります。したがって、このコードになります。
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}catch(Throwable ex){
LOG.error("The transfer for {} failed due the error {}", foundtransferVO, ex);
}
}
多くのオープンソースプロジェクトを参照して、throwable
が実際にキャッシュされて処理されていることを確認できます。たとえば、ここで、、および:の検索をtomcat
行いstruts2
ますprimefaces
。
https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch %28Throwable https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable
一般的に言って、あなたはError
sを捕まえるのを避けたいのですが、私はそうすることが適切である(少なくとも)2つの特定のケースを考えることができます:
AssertionError
それ以外の場合は無害です。Throwableは、すべてのエラーと例外のスーパークラスです。キャッチ句でThrowableを使用すると、すべての例外がキャッチされるだけでなく、すべてのエラーもキャッチされます。エラーはJVMによってスローされ、アプリケーションで処理することを意図していない重大な問題を示します。その典型的な例は、OutOfMemoryErrorまたはStackOverflowErrorです。どちらも、アプリケーションの制御が及ばず、処理できない状況が原因で発生します。したがって、Throwable内に存在する例外のみであるとかなり確信していない限り、Throwablesをキャッチするべきではありません。
スローアブルを使用する場合は、エラーもカバーします。それだけです。
例。
public class ExceptionTest {
/**
* @param args
*/
public static void m1() {
int i = 10;
int j = 0;
try {
int k = i / j;
System.out.println(k);
} catch (Throwable th) {
th.printStackTrace();
}
}
public static void main(String[] args) {
m1();
}
}
出力:
java.lang.ArithmeticException: / by zero
at com.infy.test.ExceptionTest.m1(ExceptionTest.java:12)
at com.infy.test.ExceptionTest.main(ExceptionTest.java:25)
より差別化された答えは次のようになります:それは依存します。
例外とエラーの違いは、例外は予期されなければならない状態であるのに対し、エラーは予期しない状態であり、通常は致命的であるということです。通常、エラーは回復できず、プログラムの主要部分またはJVM全体をリセットする必要があります。
例外のキャッチは、発生する可能性のある状態を処理するために常に実行する必要があることです。そのため、JVMによって強制されます。IEがファイルを開くと、FileNotFoundExceptionが発生する可能性があり、Webリソースを呼び出すと、TimeoutExceptionが発生する可能性があります。これらの状況は一般的に発生する可能性があるため、コードはこれらの状況を処理できるように準備する必要があります。それらをどのように処理するかはあなた次第です。すべてから回復する必要はありませんが、Webサーバーが応答するのに少し時間がかかったという理由だけで、アプリケーションをデスクトップに再起動するべきではありません。
エラーのキャッチは、本当に必要な場合にのみ実行する必要があります。通常、エラーから回復することはできません。正当な理由がない限り、回復を試みることはできません。エラーをキャッチする理由は、そうでなければ開いたままになる重要なリソースを閉じることです。または、プラグインを実行するサーバーがある場合は、エラーの原因となったプラグインを停止または再起動できます。他の理由は、後でそのエラーをデバッグするのに役立つ可能性のある追加情報をログに記録することです。その場合はもちろん、アプリケーションが正しく終了することを確認するためにそれを再スローする必要があります。
経験則:エラーをキャッチする重要な理由がない限り、キャッチしないでください。
したがって、そのcatch (Throwable t)
ような本当に重要な状況でのみ使用してください。catch (Exception e)