Wrapping vs Rethrowing Exceptions in Java – 在Java中包裹与重新抛出异常的问题

最后修改: 2019年 12月 17日

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

1. Overview

1.概述

The throw keyword in Java is used to explicitly throw either a custom-made exception or in-built exception. But sometimes in the catch block, we need to throw the same exception again. This leads to re-throwing an exception.

Java中的 throw关键字被用来明确地抛出自定义的异常或内置的异常。但有时在catch块中,我们需要再次抛出同一个异常。这就导致了重新抛出一个异常。

In this tutorial, we’ll discuss the two most common ways of re-throwing the exception.

在本教程中,我们将讨论重新抛出异常的两种最常见的方式。

2. Re-throwing Exceptions

2.重新抛出异常情况

Sometimes before propagating the exception to the higher level, we might want to perform some activities. For example, we might want to rollback the DB transaction, log the exception, or send an email.

有时,在向高层传播异常之前,我们可能想执行一些活动。例如,我们可能想回滚数据库事务,记录异常,或者发送电子邮件。

We can perform such activities in the catch block and re-throw the exception again. In this way, a higher level gets notified that the exception has occurred in the system.

我们可以在catch块中进行这样的活动,并再次重新抛出异常。这样一来,上级就会得到通知,知道系统中发生了异常。

Let’s understand our case with an example.

让我们通过一个例子来了解我们的情况。

Below, we’re re-throwing the same exception. And, we’re logging an error message just before throwing it:

下面,我们重新抛出了同一个异常。而且,我们在抛出异常之前记录了一条错误信息。

String name = null;

try {
    return name.equals("Joe"); // causes NullPointerException
} catch (Exception e) {
    // log
    throw e;
}

The console will show the following message:

控制台将显示以下信息。

Exception in thread "main" java.lang.NullPointerException
  at com.baeldung.exceptions.RethrowSameExceptionDemo.main(RethrowSameExceptionDemo.java:16)

As we can see, our code just rethrows any exception it catches. Because of this, we get the original stack trace without any changes.

我们可以看到,我们的代码只是重新抛出它所捕获的任何异常。正因为如此,我们得到了没有任何变化的原始堆栈跟踪

3. Wrapping Exceptions

3.包裹例外情况

Now, let’s take a look at a different approach.

现在,让我们看一下不同的方法。

In this case, we’ll pass the same exception as a reference in the constructor of a different exception:

在这种情况下,我们将在一个不同的异常的构造函数中把相同的异常作为一个引用来传递。

String name = null;

try {
    return name.equals("Joe"); // causes NullPointerException
} catch (Exception e) {
    // log
    throw new IllegalArgumentException(e);
}

The console will display:

控制台将显示。

Exception in thread "main" java.lang.IllegalArgumentException: java.lang.NullPointerException
  at com.baeldung.exceptions.RethrowDifferentExceptionDemo.main(RethrowDifferentExceptionDemo.java:24)
Caused by: java.lang.NullPointerException
  at com.baeldung.exceptions.RethrowDifferentExceptionDemo.main(RethrowDifferentExceptionDemo.java:18)

This time, we see the original exception as well as the wrapping one. In this way, our IllegalArgumentException instance wraps the original NullPointerException as a cause. Hence we can show the more specific exception instead of showing the generic one.

这一次,我们看到了原始的异常以及包裹的异常。这样,我们的IllegalArgumentException 实例就把原来的NullPointerException 包装成了一个原因。因此,我们可以显示更具体的异常,而不是显示通用异常。

4. Conclusion

4.总结

In this short article, we presented the main difference between re-throwing the original exception vs first wrapping it. Both ways differ from each other in the way they show the exception message.

在这篇短文中,我们介绍了重新抛出原始异常与先包装异常的主要区别。这两种方式 在显示异常信息的方式上有区别

Based on our requirement, we can either re-throw the same exception or wrap it with some specific exception by using the second approach. The second approach looks cleaner and easy to backtrack the exception.

根据我们的要求,我们既可以重新抛出同一个异常,也可以使用第二种方法将其包裹在某些特定的异常中。 第二种方法看起来更干净,而且容易回溯异常

As always the project is available over on GitHub.

该项目一如既往地在GitHub上提供超过