例外を一目見ただけでアプリケーションをクラッシュさせることは、非常に悪い習慣です。特に、一部の作業が保存されておらず、アプリケーションが実行を終了する前に解放してクリーンアップする必要があるリソースをアプリケーションが使用している場合。いくつかの非常に人気のあるソフトウェアはそれを行っていました...そして問題を「修正」する代わりに、アプリケーションの再起動時にデータ回復機能を導入しました。しかし、これは良いソフトウェア エンジニアリングではありません。
少なくとも、最初の例外/エラーが発生したときにアプリケーションがクラッシュすることはなく、意味のあるメッセージで回復する必要があります。RuntimeException
すべてを a (または)でラップするだけThrowable
で、特に何もしないのは面倒です。
1) 回避策、および 2) この状況を処理するためのより良い方法があるため、Java はどのような種類のフラグもサポートしていません。例えば :
1. 呼び出し元のメソッドで例外を処理する
throws
メソッド宣言にキーワードをメソッドまで追加できますstatic public void main
。例外を処理しないと、最終的にスタックトレースでアプリケーションがクラッシュします。
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) throws Throwable {
new Foo().someMethod();
}
}
この方法は回復手段を提供せず、おそらくユーザーを不幸にします (アプリケーションをコンソールから実行した場合は意味のない大量の stachtrace が表示され、ショートカットまたは GUI から起動した場合はまったく何も表示されません)。また、取得したリソースがある場合、例外が発生したときにそれらをクリーンアップできません。少なくとも、上記の例外をスローする前に何かを出力するmain
必要があります。catch (Throwable e)
何かのようなもの :
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) {
try {
new Foo().someMethod();
} catch (...) {
// output or log exception here and, optionally, cleanup and exit
}
}
}
**編集**
次のシナリオを考えてみましょう: プログラムがデータを処理するためにリソースを初期化し、処理中に実行時例外 (またはエラー) が発生し、アプリケーションがクラッシュしますが、リソースは解放または解放されません。ただし、Javaではこれを行うことができます
public E doSomething() throws RuntimeException {
// declare a bunch of resources
try {
// process resources with unchecked exceptions
} finally {
// free resources
}
// return some result
}
エラーまたは成功時にメソッドをきれいに終了し、おそらく「後世」の実行時エラーをログに記録します。
2. エラーをログに記録し、意味のある値を返す
ロギングは非常に優れた方法です。全体をクラッシュさせずに操作を実行できなかったことを伝えるメッセージをユーザーに表示し、ユーザーが何をどこで行っていたかの痕跡を示すことができます。単純なロギング システムは次のようになります。
class Foo {
static private final Logger LOG = Logger.getLogger(Foo.class.getName());
public boolean doSomethingImpl(...) {
boolean result = true;
try {
...
} catch (SomeException e) {
LOG.log(Level.SEVERE, "meaningful message why method could not do something!", e);
result = false;
}
return result;
}
public void doSomething() {
if (!doSomethingImpl(...)) {
// handle failure here
}
}
}
デフォルトでは、Logger
はすべてをerr
出力ストリームに出力しますが、独自のハンドラを追加できます:
// loggers are singletons, so you can retrieve any logger at anytime from
// anywhere, as long as you know the logger's name
Logger logger = Logger.getLogger(Foo.class.getName());
logger.setUseParentHandlers(false); // disable output to err
logger.addHandler(new MyHandler()); // MyHandler extends java.util.logging.Handler
Java にはすでにいくつかのデフォルトのロギング ハンドラが付属しており、そのうちの 1 つはfile に書き込みます。
等