1概要

このチュートリアルでは、Javaのグローバル例外ハンドラに焦点を当てます。

最初に、例外の基本と例外処理について説明します。それでは、グローバル例外ハンドラについて包括的に説明します。

一般的な例外の詳細については、https://www.baeldung.com/java-exceptions[Javaでの例外処理]を参照してください。

** 2例外とは

  • 例外とは、実行時またはコンパイル時にコードシーケンスで発生する異常な状態です。** この異常な状態は、プログラムがJavaプログラミング言語の意味上の制約に違反しているときに発生します。

  • コンパイル時に発生する例外は

    チェックされた例外

    です。** これらの例外は

    Exception

    クラスの直接のサブクラスであり、コードでこれらの例外を処理する必要があります。

  • 別の種類の例外は

    未チェックの例外

    です。コンパイラは、コンパイル時にこれらの例外をチェックしません。** これらの例外は、

    Exception

    クラスを拡張する

    RuntimeException

    クラスの直接のサブクラスです。

また、コード内でランタイム例外を処理する必要はありません。


3例外ハンドラ

Javaは堅牢なプログラミング言語です。それを堅牢にするコア機能の1つは、例外処理フレームワークです。これは、プログラムが単にクラッシュするのではなく、エラー時に正常に終了できることを意味します。

  • 例外が発生するたびに、JVMまたはコードを実行するメソッドによって

    Exception

    オブジェクトが構築されます。このオブジェクトは例外についての情報が含まれています。 ** 例外処理は、この

    Exception

    オブジェクトを処理する方法です。


3.1.

try-catch

ブロック

次の例では、

try

ブロックに例外をスローする可能性のあるコードが含まれています。

catch

ブロックには、この例外を処理するためのロジックが含まれています。


catch

ブロックは、

try

ブロック内のコードが発生させる

Exception

オブジェクトをキャッチします。

String string = "01, , 2010";
DateFormat format = new SimpleDateFormat("MM, dd, yyyy");
Date date;
try {
    date = format.parse(string);
} catch (ParseException e) {
    System.out.println("ParseException caught!");
}


3.2.

throw



throws

のキーワード

あるいは、メソッドは例外を処理する代わりに例外をスローするように選択することもできます。つまり、

Exception

オブジェクトを処理するためのロジックは別の場所に書かれています。

通常、呼び出し側のメソッドはこのような場合に例外を処理します。

public class ExceptionHandler {

    public static void main(String[]args) {

        String strDate = "01, , 2010";
        String dateFormat = "MM, dd, yyyy";

        try {
            Date date = new DateParser().getParsedDate(strDate, dateFormat);
        } catch (ParseException e) {
            System.out.println("The calling method caught ParseException!");
        }
    }
}

class DateParser {

    public Date getParsedDate(String strDate, String dateFormat) throws ParseException {
        DateFormat format = new SimpleDateFormat(dateFormat);

        try {
            return format.parse(strDate);
        } catch (ParseException parseException) {
            throw parseException;
        }
    }

}

次に、例外を処理する一般的な方法として、グローバル例外ハンドラを検討します。


4グローバル例外ハンドラ


RuntimeException

のインスタンスは、処理するためのオプションです。

そのため、実行時に長いスタックトレースを取得するためのウィンドウは開いたままになります。これを処理するために、

Javaは

__UncaughtExceptionHandler


interface


を提供します。 Thread__クラスはこれを内部クラスとして含みます。

このインタフェースに加えて、Java 1.5リリースでは

Thread

クラスに静的メソッド

setDefaultUncaughtExceptionHandler()

も導入されました。このメソッドの引数は、

UncaughtExceptionHandler

インタフェースを実装するハンドラクラスです。

さらに、このインタフェースはメソッド

uncaughtException(Thread t、Throwable e)

を宣言しています。指定されたスレッド

t

が、指定されたキャッチされていない例外

e

のために終了したときに呼び出されます。実装クラスはこのメソッドを実装し、これらの捕捉されていない例外を処理するためのロジックを定義します。

実行時に

ArithmeticException

をスローする次の例を考えてみましょう。インタフェース

UncaughtExceptionHandler

を実装するクラス

Handler

を定義します。

このクラスはメソッド

uncaughtException()

を実装し、その中の捕捉されていない例外を処理するロジックを定義します。

public class GlobalExceptionHandler {

    public static void main(String[]args) {

        Handler globalExceptionHandler = new Handler();
        Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
        new GlobalExceptionHandler().performArithmeticOperation(10, 0);
    }

    public int performArithmeticOperation(int num1, int num2) {
        return num1/num2;
    }
}

class Handler implements Thread.UncaughtExceptionHandler {

    private static Logger LOGGER = LoggerFactory.getLogger(Handler.class);

    public void uncaughtException(Thread t, Throwable e) {
        LOGGER.info("Unhandled exception caught!");
    }
}

ここでは、現在実行中のスレッドがメインスレッドです。したがって、そのインスタンスは、発生した例外とともにメソッド

uncaughtException()

に渡されます。その後、クラス

Handler

がこの例外を処理します。

未処理のチェック済み例外も同様です。この簡単な例も見てみましょう。

public static void main(String[]args) throws Exception {
    Handler globalExceptionHandler = new Handler();
    Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
    Path file = Paths.get("");
    Files.delete(file);
}

ここでは、

Files.delete()メソッドがチェックされた

IOExceptionをスローします。これは、さらに

main()メソッドシグネチャによってスローされます。

Handler__もこの例外をキャッチします。

このように、

UncaughtExceptionHandler

は、実行時に未処理の例外を管理するのに役立ちます。しかし、それは例外を捕捉して起点の近くで処理するという考えを壊します。


5結論

この記事では、例外とは何か、そしてそれらを処理する基本的な方法は何かを理解するのに時間がかかりました。また、グローバル例外ハンドラは

Thread

クラスの一部であり、キャッチされていないランタイム例外を処理することを確認しました。

次に、ランタイム例外をスローし、グローバル例外ハンドラを使用して処理するサンプルプログラムを見ました。

この記事のコード例はhttps://github.com/eugenp/tutorials/tree/master/core-java[GitHubで利用可能]です。