Chained Exceptions in Java – Java中的链式异常

最后修改: 2017年 1月 27日

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

 

1. Overview

1.概述

In this article, we’ll have a very brief look at what Exception is and go in depth about discussing the chained exceptions in Java.

在这篇文章中,我们将非常简要地了解什么是Exception,并深入地讨论Java中的连锁异常。

Simply put, an exception is an event that disturbs the normal flow of the program’s execution. Let’s now see exactly how we can chain exceptions to get better semantics out of them.

简单地说,异常是一个扰乱了程序正常执行流程的事件。现在让我们看看到底如何通过连锁异常来获得更好的语义。

2. Chained Exceptions

2.链式异常

Chained Exception helps to identify a situation in which one exception causes another Exception in an application.

链式Exception有助于识别应用程序中一个异常导致另一个Exception的情况。

For instance, consider a method which throws an ArithmeticException because of an attempt to divide by zero but the actual cause of exception was an I/O error which caused the divisor to be zero.The method will throw the ArithmeticException to the caller. The caller would not know about the actual cause of an Exception. Chained Exception is used in such situations.

例如,考虑一个方法抛出一个ArithmeticException,因为它试图除以0,但异常的实际原因是一个I/O错误,导致除数为0。这个方法将抛出ArithmeticException给调用者。调用者不会知道Exception的实际原因。链式Exception在这种情况下使用。

This concept was introduced in JDK 1.4.

这个概念是在JDK 1.4中引入的。

Let’s see how chained exceptions are supported in Java.

让我们看看Java中是如何支持链式异常的。

3. Throwable Class

3.可抛物

Throwable class has some constructors and methods to support chained exceptions. Firstly, let’s look at the constructors.

Throwable类有一些构造函数和方法来支持链式异常。首先,让我们看一下构造函数。

  • Throwable(Throwable cause) Throwable has a single parameter, which specifies the actual cause of an Exception.
  • Throwable(String desc, Throwable cause)this constructor accepts an Exception description with the actual cause of an Exception as well.

Next, let’s have a look at the methods this class provides:

接下来,让我们看看这个类所提供的方法。

  • getCause() method – This method returns the actual cause associated with current Exception.
  • initCause() method – It sets an underlying cause with invoking Exception.

4. Example

4.实例

Now, let’s look at the example where we will set our own Exception description and throw a chained Exception:

现在,让我们看看这个例子,我们将设置自己的Exception描述,并抛出一个链式Exception

public class MyChainedException {

    public void main(String[] args) {
        try {
            throw new ArithmeticException("Top Level Exception.")
              .initCause(new IOException("IO cause."));
        } catch(ArithmeticException ae) {
            System.out.println("Caught : " + ae);
            System.out.println("Actual cause: "+ ae.getCause());
        }
    }    
}

As guessed, this will lead to:

正如猜测的那样,这将导致。

Caught: java.lang.ArithmeticException: Top Level Exception.
Actual cause: java.io.IOException: IO cause.

5. Why Chained Exceptions?

5.为什么是链式异常?

We need to chain the exceptions to make logs readable. Let’s write two examples. First without chaining the exceptions and second, with chained exceptions. Later, we will compare how logs behave in both of the cases.

我们需要对异常进行连锁处理,使日志可读。我们来写两个例子。首先是没有连锁的异常,其次是有连锁的异常。稍后,我们将比较这两种情况下日志的表现。

To start, we will create a series of Exceptions:

首先,我们将创建一系列的异常。

class NoLeaveGrantedException extends Exception {

    public NoLeaveGrantedException(String message, Throwable cause) {
        super(message, cause);
    }

    public NoLeaveGrantedException(String message) {
        super(message);
    }
}

class TeamLeadUpsetException extends Exception {
    // Both Constructors
}

Now, let’s start using the above exceptions in code examples.

现在,让我们开始在代码示例中使用上述异常。

5.1. Without Chaining

5.1.没有连锁反应

Let’s write an example program without chaining our custom exceptions.

让我们来写一个没有链入我们自定义异常的例子程序。

public class MainClass {

    public void main(String[] args) throws Exception {
        getLeave();
    }

    void getLeave() throws NoLeaveGrantedException {
        try {
            howIsTeamLead();
        } catch (TeamLeadUpsetException e) {
            e.printStackTrace();
            throw new NoLeaveGrantedException("Leave not sanctioned.");
        }
    }

    void howIsTeamLead() throws TeamLeadUpsetException {
        throw new TeamLeadUpsetException("Team Lead Upset");
    }
}

In the example above, logs will look like this:

在上面的例子中,日志将看起来像这样。

com.baeldung.chainedexception.exceptions.TeamLeadUpsetException: 
  Team lead Upset
    at com.baeldung.chainedexception.exceptions.MainClass
      .howIsTeamLead(MainClass.java:46)
    at com.baeldung.chainedexception.exceptions.MainClass
      .getLeave(MainClass.java:34)
    at com.baeldung.chainedexception.exceptions.MainClass
      .main(MainClass.java:29)
Exception in thread "main" com.baeldung.chainedexception.exceptions.
  NoLeaveGrantedException: Leave not sanctioned.
    at com.baeldung.chainedexception.exceptions.MainClass
      .getLeave(MainClass.java:37)
    at com.baeldung.chainedexception.exceptions.MainClass
      .main(MainClass.java:29)

5.2. With Chaining

5.2.有链子

Next, let’s write an example with chaining our custom exceptions:

接下来,让我们写一个例子,把我们的自定义异常连锁起来。

public class MainClass {
    public void main(String[] args) throws Exception {
        getLeave();
    }

    public getLeave() throws NoLeaveGrantedException {
        try {
            howIsTeamLead();
        } catch (TeamLeadUpsetException e) {
             throw new NoLeaveGrantedException("Leave not sanctioned.", e);
        }
    }

    public void howIsTeamLead() throws TeamLeadUpsetException {
        throw new TeamLeadUpsetException("Team lead Upset.");
    }
}

Finally, let’s look at the logs obtained with chained exceptions:

最后,让我们看看用链式异常获得的日志。

Exception in thread "main" com.baeldung.chainedexception.exceptions
  .NoLeaveGrantedException: Leave not sanctioned. 
    at com.baeldung.chainedexception.exceptions.MainClass
      .getLeave(MainClass.java:36) 
    at com.baeldung.chainedexception.exceptions.MainClass
      .main(MainClass.java:29) 
Caused by: com.baeldung.chainedexception.exceptions
  .TeamLeadUpsetException: Team lead Upset.
    at com.baeldung.chainedexception.exceptions.MainClass
  .howIsTeamLead(MainClass.java:44) 
    at com.baeldung.chainedexception.exceptions.MainClass
  .getLeave(MainClass.java:34) 
    ... 1 more

We can easily compare shown logs and conclude that the chained exceptions lead to cleaner logs.

我们可以很容易地比较显示的日志,并得出结论,链式异常导致更干净的日志。

6. Conclusion

In this article, we had a look at chained exceptions concept.

在这篇文章中,我们看了一下链式异常的概念。

The implementation of all examples can be found in the Github project – this is a Maven-based project, so it should be easy to import and run as it is.

所有例子的实现都可以在Github项目中找到–这是一个基于Maven的项目,所以应该很容易按原样导入和运行。