Java Global Exception Handler – Java全局异常处理程序

最后修改: 2018年 7月 9日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll focus on the Global Exception Handler in Java. We’ll first discuss the basics of the exceptions and the exception handling. Then we’ll have a comprehensive look on the global exception handler.

在本教程中,我们将重点讨论Java中的全局异常处理程序。我们将首先讨论异常和异常处理的基础知识。然后,我们将全面了解全局异常处理程序。

To learn more about the exceptions in general, have a look at Exception Handling in Java.

要了解更多关于异常的一般情况,请看Java中的异常处理

2. What Is an Exception?

2.什么是例外?

An exception is an abnormal condition that arises in a code sequence at runtime or at compile time. This abnormal condition arises when a program violates the semantic constraints of the Java programming language.

异常是指在运行时或编译时在代码序列中出现的异常情况。当程序违反了Java编程语言的语义约束时,就会出现这种异常情况。

Exceptions that occur during the compile time are checked exceptions. These exceptions are direct subclasses of the Exception class, and it’s necessary to handle these exceptions in the code.

在编译时发生的异常是被检查的异常这些异常是Exception类的直接子类,有必要在代码中处理这些异常。

Another type of exceptions are the unchecked exceptions. The compiler does not check for these exceptions during the compile time. These exceptions are direct subclasses of the RuntimeException class which extends the Exception class.

另一种类型的异常是未检查的异常。编译器在编译时不检查这些异常。这些异常是RuntimeException类的直接子类,它扩展了Exception类。

Also, it’s not necessary to handle runtime exceptions in the code.

另外,没有必要在代码中处理运行时异常。

3. Exception Handlers

3.异常处理程序

Java is a robust programming language. One of the core features that makes it robust is the exception handling framework. It means the program can gracefully exit at the times of error, instead of just crashing.

Java是一种健壮的编程语言。使其健壮的核心特征之一是异常处理框架。这意味着程序可以在出现错误时优雅地退出,而不是直接崩溃。

Whenever an exception occurs, an Exception object is constructed, either by the JVM or by the method executing the code. This object contains the information about the exception. Exception handling is a way of handling this Exception object.

每当异常发生时,就会构造一个Exception对象,可以由JVM或者执行代码的方法来完成。这个对象包含了关于异常的信息。异常处理是处理这个Exception对象的一种方式

3.1. The try-catch Block

3.1.try-catch

In the following example, the try block contains the code which can throw an exception. The catch block contains the logic to handle this exception.

在下面的例子中,try块包含可以抛出一个异常的代码。catch块包含处理该异常的逻辑。

The catch block catches the Exception object that the code in the try block raises:

catch块捕捉Exception对象,try块中的代码引发了该对象。

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. The throw and throws Keywords

3.2.throwthrows关键词

Alternatively, the method can also choose to throw the exception instead of handling it. That means the logic to handle the Exception object is written somewhere else.

另外,该方法也可以选择抛出异常而不是处理它。这意味着处理Exception对象的逻辑被写在其他地方。

Usually, the calling method handles the exception in such cases:

通常,在这种情况下,调用方法会处理异常。

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;
        }		
    }
	
}

Next, we’ll consider the Global Exception Handler, as a generic way to handle exceptions.

接下来,我们将考虑全局异常处理程序,作为处理异常的一种通用方法。

4. Global Exception Handler

4.全局异常处理程序

The instances of the RuntimeException are optional to handle. Consequently, it still leaves a window open for getting the long stack traces at runtime. To handle this, Java provides the UncaughtExceptionHandler interface. The Thread class contains this as an inner class.

RuntimeException的实例是可以选择处理的。因此,它仍然为在运行时获得长的堆栈痕迹留下了一个窗口。为了处理这个问题,Java提供了UncaughtExceptionHandlerinterfaceThread类将其作为一个内类包含。

In addition to this interface, Java 1.5 release also introduced a static method setDefaultUncaughtExceptionHandler() in the Thread class. The argument of this method is a handler class that implements the UncaughtExceptionHandler interface.

除了这个接口之外,Java 1.5版本还在Thread类中引入了一个静态方法setDefaultUncaughtExceptionHandler()。该方法的参数是一个实现UncaughtExceptionHandler接口的处理程序类。

Furthermore, this interface declares the method uncaughtException(Thread t, Throwable e). It will be invoked when a given thread t terminates due to the given uncaught exception e. The implementing class implements this method and defines the logic for handling these uncaught exceptions.

此外,该接口声明了方法uncaughtException(Thread t, Throwable e)。当一个给定的线程t由于给定的未捕获异常e而终止时,它将被调用。实现类实现了这个方法并定义了处理这些未捕获异常的逻辑。

Let’s consider the following example that throws an ArithmeticException at runtime. We define the class Handler that implements the interface UncaughtExceptionHandler.

让我们考虑下面的例子,在运行时抛出一个ArithmeticException。我们定义了一个Handler类,它实现了UncaughtExceptionHandler接口。

This class implements the method uncaughtException() and defines logic to handle uncaught exceptions in it:

这个类实现了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!");
    }
}

Here, the currently executing thread is the main thread. Thus, its instance is passed to the method uncaughtException() along with the raised exception. The class Handler then handles this exception.

这里,当前执行的线程是主线程。因此,它的实例被传递给方法uncaughtException()以及引发的异常。然后由Handler类来处理这个异常。

The same applies to unhandled checked exceptions. Let’s see a quick example of this as well:

这同样适用于未处理的检查异常。让我们也来看看这方面的一个简单例子。

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

Here, the Files.delete() method throws a checked IOException, which is further thrown by the main() method signature. The Handler will catch this exception as well.

在这里,Files.delete()方法抛出了一个被检查的IOException,,它被main()方法签名进一步抛出。Handler也将捕获这个异常。

In this way, the UncaughtExceptionHandler helps in managing unhandled exceptions at runtime. However, it breaks the idea of catching and handling the exception close to the point of origin.

通过这种方式,UncaughtExceptionHandler有助于在运行时管理未处理的异常。然而,它打破了在原点附近捕捉和处理异常的想法

5. Conclusion

5.结论

In this article, we took time to understand what the exceptions are, and what are the basic ways to handle them. Also, we identified that the global exception handler is a part of the Thread class and it handles the uncaught runtime exceptions.

在这篇文章中,我们花时间了解了什么是异常,以及处理异常的基本方法是什么。此外,我们还确定了全局异常处理程序是Thread类的一部分,它处理未捕获的运行时异常。

Then, we saw a sample program that throws a runtime exception and handles it using a global exception handler.

然后,我们看到了一个抛出运行时异常并使用全局异常处理程序来处理它的示例程序。

The example codes for this article can be found over on GitHub.

本文的示例代码可以在GitHub上找到over