Javaでいくつかの例外がcatch (Exception ex)
でキャッチされないのはなぜですか?これは、未処理の例外で完全に失敗するコードです(Javaバージョン1.4)。
public static void main(String[] args) {
try {
//Code ...
} catch (Exception ex) {
System.err.println("Caught Exception");
ex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
}
finally {
app.shutdown();
}
System.exit(exitCode);
}
Exception in thread "main" Java.lang.NoSuchMethodError
しかし、これはうまくいきます
public static void main(String[] args) {
int exitCode = app.SUCCESS_EXIT_CODE;
try {
//Code ...
} catch (Java.lang.NoSuchMethodError mex){
System.err.println("Caught NoSuchMethodError");
mex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
} catch (Exception ex) {
System.err.println("Caught Exception");
ex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
}
finally {
app.shutdown();
}
System.exit(exitCode);
}
Caught NoSuchMethodError Java.lang.NoSuchMethodError:
例外をキャッチするとすべての例外をキャッチできると思いましたか? Javaですべての例外をキャッチするにはどうすればよいですか?
一部の例外はException
から派生していないためです。 Throwable
およびError
。
基本的に、タイプ階層は次のとおりです。
Object
|
Throwable
/ \
Exception Error
スローできるのはThrowables
と派生クラスのみなので、Throwable
をキャッチすると、すべてがキャッチされます。
Throwable
、Exception
、およびException
から派生するすべての例外otherRuntimeException
から派生したもの以外はチェックされた例外としてカウントされます-それらは、スローするか、スローするものを呼び出す場合にキャッチすることを宣言する必要があるものです。
Java例外階層は少し混乱しています...
クラスExceptionとそのサブクラスは、合理的なアプリケーションがキャッチする可能性のある条件を示すThrowableの形式です。
- JavaDoc for Java.lang.Exception
Errorは、Throwableのサブクラスであり、妥当なアプリケーションがキャッチしようとしてはならない重大な問題を示します。
ThreadDeath など、特定のエラーをキャッチしたい場合があります。以下で説明するように、ThreadDeathはエラーとして分類されます。
ThreadDeathクラスは、「通常の発生」であっても、具体的にはExceptionではなくErrorのサブクラスです。これは、多くのアプリケーションがExceptionの発生をすべてキャッチしてから、例外を破棄するためです。
ただし、Threadのstop()メソッドは廃止されたため、使用しないでください。したがって、ThreadDeathが表示されることはありません。
例外はThrowableの一種にすぎません。 NoSuchMethodErrorは例外ではなくエラーです。これは別の種類のThrowableです。
Throwable
をキャッチできます。エラーと例外はThrowable
を拡張します。
throwable JavaDoc を参照してください:
Throwableクラスは、Java言語のすべてのエラーと例外のスーパークラスです。
他のポスターが指摘しているように、すべてのスロー可能なオブジェクトがException
のサブクラスであるとは限りません。ただし、ほとんどの場合、Error
またはThrowable
をキャッチすることはお勧めできません。これらの条件には、簡単に回復できない非常に深刻なエラー条件が含まれているためです。あなたの回復コードは物事を悪化させるだけかもしれません。
最初に、この議論におけるいくつかの不幸な意味の混乱を明らかにしましょう。 Java.lang.Exception
クラスがあり、これを単に大文字の「E」を使用した例外と呼ぶことができます。次に、言語機能である小文字の「e」を除いて例外があります。小文字バージョンはThrowable
クラスの documentation で確認できます。
例外のコンパイル時チェックのために、Throwable、およびRuntimeExceptionまたはErrorのサブクラスではないThrowableのサブクラスは、チェックされた例外と見なされます。
私にとっては、この質問に対する答えを、チェック済みの例外とチェックなしの例外(小文字のe)として考える方が簡単です。チェックされた例外はコンパイル時に考慮する必要がありますが、チェックされていない例外は考慮されません。例外(大文字のE)とそのサブクラスはチェックされた例外です。つまり、コードによってスローされる可能性のある例外をキャッチするか、メソッドがスローできる例外をキャッチする必要があります(キャッチされない場合)。
エラーとそのサブクラスは未チェックの例外です。つまり、コードはスローされる可能性のあるエラーをキャッチする必要がなく、それらのエラーをスローすることを宣言する必要もありません。 RunTimeExceptionとそのサブクラスも、クラス階層内の場所に関係なく、チェックされない例外です。
次のコードを検討してください。
void test() {
int a = 1, b = 0, c = a / b;
}
実行すると、上記のコードはJava.lang.ArithmeticException
を生成します。これは、例外がスローされ、コードがArithmeticExceptionをキャッチしたり、この例外をスローすることを宣言したりしていなくても、エラーなしでコンパイルされます。これは、チェックされていない例外の本質です。
クラス階層内のArithmeticException
の場所を考慮してください。特に、これがJava.lang.Exceptionのサブクラスであるという事実を考慮してください。ここには、Java.lang.Exceptionから派生した例外がありますが、これはJava.lang.RuntimeExceptionのサブクラスでもあるため、チェックされていない例外なので、キャッチする必要はありません。
Java.lang.Object
Java.lang.Throwable
Java.lang.Exception
Java.lang.RuntimeException
Java.lang.ArithmeticException
スローされる可能性のあるものをキャッチしたい場合は、Throwableをキャッチしてください。ただし、これらのThrowableの一部は、キャッチされるべきではない致命的な実行時の状態になる可能性があるため、これは最も安全な方法ではない可能性があります。または、Throwableをキャッチした場合、処理できないThrowableを再スローすることもできます。状況によります。