Create a Custom Exception in Java – 在Java中创建一个自定义异常

最后修改: 2018年 7月 2日

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

1. Overview

1.概述

In this tutorial, we’ll cover how to create a custom exception in Java.

在本教程中,我们将介绍如何在Java中创建一个自定义的异常

We’ll show how user-defined exceptions are implemented and used for both checked and unchecked exceptions.

我们将展示用户定义的异常是如何实现的,并用于检查和未检查的异常。

2. The Need for Custom Exceptions

2.自定义例外的必要性

Java exceptions cover almost all general exceptions that are bound to happen in programming.

Java异常涵盖了几乎所有在编程中必然会发生的一般异常。

However, we sometimes need to supplement these standard exceptions with our own.

然而,我们有时需要用我们自己的方式来补充这些标准的例外情况。

These are the main reasons for introducing custom exceptions:

这些是引入自定义异常的主要原因。

  • Business logic exceptions – exceptions that are specific to the business logic and workflow. These help the application users or the developers understand what the exact problem is.
  • To catch and provide specific treatment to a subset of existing Java exceptions

Java exceptions can be checked and unchecked. In the next sections, we’ll cover both of these cases.

Java 异常可以被检查和不被检查。在接下来的章节中,我们将介绍这两种情况。

3. Custom Checked Exception

3.自定义检查的异常

Checked exceptions are exceptions that need to be treated explicitly.

被检查的异常是需要被明确处理的异常。

Let’s consider a piece of code that returns the first line of the file:

让我们考虑一段返回文件第一行的代码。

try (Scanner file = new Scanner(new File(fileName))) {
    if (file.hasNextLine()) return file.nextLine();
} catch(FileNotFoundException e) {
    // Logging, etc 
}

The code above is a classic way of handling Java checked exceptions. While the code throws FileNotFoundException, it’s not clear what the exact cause is — whether the file doesn’t exist or the file name is invalid.

上面的代码是处理Java检查异常的一个经典方法。虽然代码抛出了FileNotFoundException,但并不清楚具体原因是什么–是文件不存在还是文件名无效。

To create a custom exception, we have to extend the java.lang.Exception class.

为了创建一个自定义的异常,我们必须扩展java.lang.Exception类。

Let’s see an example of this by creating a custom checked exception called IncorrectFileNameException:

让我们通过创建一个名为IncorrectFileNameException的自定义检查异常来看看这个例子。

public class IncorrectFileNameException extends Exception { 
    public IncorrectFileNameException(String errorMessage) {
        super(errorMessage);
    }
}

Note that we also have to provide a constructor that takes a String as the error message and called the parent class constructor.

请注意,我们还必须提供一个构造函数,它接收一个String作为错误信息并调用父类的构造函数。

This is all we need to do to define a custom exception.

这就是我们需要做的所有事情,以定义一个自定义异常。

Next, let’s see how we can use the custom exception in our example:

接下来,让我们看看如何在我们的例子中使用自定义异常。

try (Scanner file = new Scanner(new File(fileName))) {
    if (file.hasNextLine())
        return file.nextLine();
} catch (FileNotFoundException e) {
    if (!isCorrectFileName(fileName)) {
        throw new IncorrectFileNameException("Incorrect filename : " + fileName );
    }
    //...
}

We’ve created and used a custom exception, so the user can now know what the exact exception is.

我们已经创建并使用了一个自定义异常,所以用户现在可以知道具体的异常是什么。

Is this enough? We are consequently losing the root cause of the exception.

这样做够吗?我们因此而失去了异常的根本原因。

To fix this, we can also add a java.lang.Throwable parameter to the constructor. This way, we can pass the root exception to the method call:

为了解决这个问题,我们也可以在构造函数中添加一个java.lang.Throwable参数。这样一来,我们就可以把根本的异常传递给方法调用。

public IncorrectFileNameException(String errorMessage, Throwable err) {
    super(errorMessage, err);
}

Now the IncorrectFileNameException is used along with the root cause of the exception:

现在,IncorrectFileNameException和异常的根本原因一起被使用。

try (Scanner file = new Scanner(new File(fileName))) {
    if (file.hasNextLine()) {
        return file.nextLine();
    }
} catch (FileNotFoundException err) {
    if (!isCorrectFileName(fileName)) {
        throw new IncorrectFileNameException(
          "Incorrect filename : " + fileName , err);
    }
    // ...
}

This is how we can use custom exceptions without losing the root cause from which they occurred.

这就是我们如何使用自定义异常的方法而不失去发生异常的根本原因

4. Custom Unchecked Exception

4.自定义未检查的异常

In our same example, let’s assume that we need a custom exception if the file name doesn’t contain any extension.

在我们的同一个例子中,让我们假设,如果文件名不包含任何扩展名,我们需要一个自定义的异常。

In this case, we’ll need a custom unchecked exception similar to the previous one, as this error will only be detected during runtime.

在这种情况下,我们需要一个类似于前一个的自定义未检查异常,因为这个错误只会在运行时被检测到。

To create a custom unchecked exception, we need to extend the java.lang.RuntimeException class:

为了创建一个自定义的未检查的异常,我们需要扩展java.lang.RuntimeException

public class IncorrectFileExtensionException 
  extends RuntimeException {
    public IncorrectFileExtensionException(String errorMessage, Throwable err) {
        super(errorMessage, err);
    }
}

This way, we can use this custom unchecked exception in our example:

这样,我们就可以在我们的例子中使用这个自定义的未检查的异常。

try (Scanner file = new Scanner(new File(fileName))) {
    if (file.hasNextLine()) {
        return file.nextLine();
    } else {
        throw new IllegalArgumentException("Non readable file");
    }
} catch (FileNotFoundException err) {
    if (!isCorrectFileName(fileName)) {
        throw new IncorrectFileNameException(
          "Incorrect filename : " + fileName , err);
    }
    
    //...
} catch(IllegalArgumentException err) {
    if(!containsExtension(fileName)) {
        throw new IncorrectFileExtensionException(
          "Filename does not contain extension : " + fileName, err);
    }
    
    //...
}

5. Conclusion

5.结论

Custom exceptions are very useful when we need to handle specific exceptions related to the business logic. When used properly, they can serve as a practical tool for better exception handling and logging.

当我们需要处理与业务逻辑相关的特定异常时,自定义异常非常有用。如果使用得当,它们可以作为一个实用的工具来更好地处理异常和记录。

The code for the examples used in this article is available over on GitHub.

本文所使用的例子的代码可在GitHub上找到