Java 言語では、例外は次の 2 つのカテゴリに分類されます。
チェック例外:このタイプの例外は、 throws 句で明示的にスローするか、メソッド内でキャッチする必要があります。たとえば、IOException や ClassNotFoundException などです。
未チェック例外:このタイプの例外は、明示的にスローしたりキャッチしたりする必要はありません。たとえば、NumberFormatException です。
Thread オブジェクトの run() メソッドでチェックされた例外がスローされた場合、 run() メソッドは例外をスローできないため、それをキャッチして処理する必要があります。 Thread オブジェクトの run() メソッドで未チェック例外がスローされた場合、デフォルトの動作では、スタック トレース情報がコンソールに出力され、プログラムが終了します。
幸いなことに、Java は、プログラムの終了を回避するために Thread オブジェクトによってスローされた未チェック例外を処理するように特別に設計されたメカニズムを提供します。
このセクションでは、例を使用してこのメカニズムを説明します。
それを知っています
この例を実装するには、以下に示す手順に従ってください。
1. まず、未チェック例外を処理するクラスを実装する必要があります。このクラスは UncaughtExceptionHandler クラスを実装し、このインターフェイスで宣言された uncaughtException() メソッドを実装する必要があります。この例では、クラス名は ExceptionHandler で、uncaughtException() メソッドは例外と例外をスローしたスレッド情報を出力します。コードは次のとおりです。
次のようにコードをコピーします。
public class ExceptionHandler は Thread.UncaughtExceptionHandler を実装します {
@オーバーライド
public void uncaughtException(Thread t, Throwable e) {
System.out.printf("例外がキャプチャされました//n");
System.out.printf("スレッド: %s/n", t.getId());
System.out.printf("例外: %s: %s/n", e.getClass().getName(),
e.getMessage());
System.out.printf("スタック トレース: /n");
e.printStackTrace(System.out);
System.out.printf("スレッドのステータス: %s/n", t.getState());
}
}
2. 未チェック例外をスローできる Task というクラスを実装し、Runnable インターフェイスを実装し、run() メソッドを実装して、未チェック例外を生成できるコード (文字列を数値に変換するなど) を特別にコーディングします。コードは次のとおりです。
次のようにコードをコピーします。
public class Task は Runnable {を実装します
@オーバーライド
public void run() {
int numero = Integer.parseInt("diguage.com");
}
}
3. プログラムのメインクラスである Main クラスを作成し、main() メソッドを実装します。コードは次のとおりです。
次のようにコードをコピーします。
パブリッククラス Main {
public static void main(String[] args) {
4. Task オブジェクトを作成し、それを実行するための Thread オブジェクトを作成します。 setUncaughtExceptionHandler() メソッドを使用して、未チェック例外の処理クラスを設定します。次に、スレッドを開始します。コードは次のとおりです。
次のようにコードをコピーします。
タスク task = new Task();
スレッド thread = 新しいスレッド(タスク);
thread.setUncaughtExceptionHandler(new ExceptionHandler());
thread.start();
5. 例を実行し、結果を表示します。
理由を知っています
異常な実行の結果は、以下の出力スニペットから確認できます。例外がスローされ、ハンドラー クラスによってキャッチされ、例外情報がコンソールに出力されます。
次のようにコードをコピーします。
例外が捕捉されました
スレッド: 9
例外: java.lang.NumberFormatException: 入力文字列の場合: "diguage.com"
スタック トレース:
java.lang.NumberFormatException: 入力文字列の場合: "diguage.com"
java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) で
java.lang.Integer.parseInt(Integer.java:492) で
java.lang.Integer.parseInt(Integer.java:527) で
com.diguage.books.concurrencycookbook.chapter1.recipe8.Task.run(Task.java:13) で
java.lang.Thread.run(Thread.java:722) で
スレッドのステータス: 実行可能
プロセスは終了コード 0 で終了しました
スレッドが例外をスローし、その例外 (ここでは特に未チェック例外を指します) がキャッチされなかった場合、Java 仮想マシンは、対応するメソッド uncaughtException() メソッドを通じて未チェック例外処理クラスが設定されているかどうかを確認します。そして、スレッドと例外をパラメータとしてメソッドに渡します。
処理クラスが設定されていない場合、Java 仮想マシンはスタック トレース情報をコンソールに出力し、プログラムを終了します。
終わりのない
Thread クラスには、未チェック例外処理に関するメソッドもあります。これは静的メソッド setDefaultUncaughtExceptionHandler() で、プログラム内のすべてのスレッドに未チェック例外処理クラスを設定できます。
キャッチされなかった例外がスレッドでスローされると、Java 仮想マシンは次の 3 つの場所から例外処理クラスを探します。
まず、スレッド オブジェクトから例外処理クラスを探します。これがこのセクションで学習したことです。存在しない場合は、スレッドが存在するスレッドグループ(ThreadGroup)から例外処理クラスを検索します。この部分については後ほど具体的に説明する。それでも存在しない場合は、上で説明したプログラムのデフォルトの例外処理クラスを探してください。
上記の例外ハンドラーがいずれも存在しない場合、Java 仮想マシンは例外のスタック トレース情報をコンソールに出力し、プログラムを終了します。
ドクトリンを使用する
この記事は「Java 7 Concurrency Cookbook」(D Gua Ge が「Java7 Concurrency Example Collection」として盗用しました) を翻訳したものであり、学習教材としてのみ使用されます。許可なく商業目的で使用することはできません。
小さな成功
ExceptionHandler クラスの完全なコードは次のとおりです。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe8;
/**
* 未チェック例外処理クラス
* 日付: 2013-09-22
* 時間: 23:11
*/
public class ExceptionHandler は Thread.UncaughtExceptionHandler を実装します {
@オーバーライド
public void uncaughtException(Thread t, Throwable e) {
System.out.printf("例外がキャプチャされました/n");
System.out.printf("スレッド: %s/n", t.getId());
System.out.printf("例外: %s: %s/n", e.getClass().getName(),
e.getMessage());
System.out.printf("スタック トレース: /n");
e.printStackTrace(System.out);
System.out.printf("スレッドのステータス: %s/n", t.getState());
}
}
Task クラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe8;
/**
※例外発生クラス
* 日付: 2013-09-22
* 時間: 23:18
*/
public class Task は Runnable {を実装します
@オーバーライド
public void run() {
int numero = Integer.parseInt("diguage.com");
}
}
Mainクラスの完全なコード
次のようにコードをコピーします。
パッケージ com.diguage.books.concurrencycookbook.chapter1.recipe8;
/**
* 例のメインクラス
* 日付: 2013-09-22
※時間:23:20
*/
パブリッククラス Main {
public static void main(String[] args) {
タスク task = new Task();
スレッド thread = 新しいスレッド(タスク);
thread.setUncaughtExceptionHandler(new ExceptionHandler());
thread.start();
}
}