Java异常处理最佳实践

在Java开发中,异常处理并非易事。其处理方式不但初学者常感觉难以理解,有时甚至经验丰富的程序员也需要花费数个小时来梳理该处理哪些异常,又如何处理这些异常。因而许多开发团队都有自己的一套规范来规定如何进行异常处理。如果你新加入一个团队,你可能会发现新团队的异常处理机制与你之前的团队有着极大的区别。然而,针对Java异常处理,本文提出了9点最佳实践建议,通过在项目中实践这些建议,将会帮助你逐渐提升异常处理能力。

1.在finally代码块中清理不再使用的资源或者使用Try-with-rerource语句

项目开发中打开外部资源在所难免,比如InputStream,你需要在使用结束之后手动关闭之。经常有新手犯错误将close语句放置在try语句块中。

public void doNotCloseResourceInTry() {
    FileInputStream inputStream = null;
    try {
        File file = new File("./tmp.txt");
        inputStream = new FileInputStream(file);
        // use the inputStream to read a file
        // do NOT do this
        inputStream.close();
    } catch (FileNotFoundException e) {
        log.error(e);
    } catch (IOException e) {
        log.error(e);
    }
}

以上的代码问题在于如果没有异常抛出,代码执行得妥妥的,try语句块中的所有语句都会被依次执行,资源也被顺利关闭。然而一旦在close语句之前抛出异常,则close语句便不会再被执行,因而使用到的资源也就无法被及时关闭。因此,开发者们应该在finally代码块中清理不再使用的资源或者使用Try-with-rerource语句。

使用Finally语句块

finally语句块无论try语句块中是否抛出异常,其中的代码最终仍会被执行。因而,如果将资源清理代码放置于此最合适不过了。

public void closeResourceInFinally() {
    FileInputStream inputStream = null;
    try {
        File file = new File("./tmp.txt");
        inputStream = new FileInputStream(file);
        // use the inputStream to read a file
    } catch (FileNotFoundException e) {
        log.error(e);
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                log.error(e);
            }
        }
    }
}

使用Java7新引入的Try-With-Resource语句

如果使用到的资源实现了AutoCloseable接口(大部分Java标准资源均已实现),便可以使用Java7中新引入的Try-With-Resource语句将其自动关闭。

public void automaticallyCloseResource() {
    File file = new File("./tmp.txt");
    try (FileInputStream inputStream = new FileInputStream(file);) {
        // use the inputStream to read a file
    } catch (FileNotFoundException e) {
        log.error(e);
    } catch (IOException e) {
        log.error(e);
    }
}

2.优先使用明确的异常

抛出的异常越明确,往往越好。永远记住,你的小伙伴们并不想关心你的代码,有时甚至你自己过了一段时间之后也会需要调用之前写好的方法并自己去处理这些异常。因此,尽可能多得提供这些异常的信息极为重要,这将使你的API更具可读性。你的代码的调用者也会从心里感激你滴。尽可能为你的异常找到最为切实的异常类,例如,抛出NumberFormatException,而不是抛出IllegalArgumentException。特别注意,不要直接抛出Exception。

public void doNotDoThis() throws Exception {
    ...
}
public void doThis() throws NumberFormatException {
    ...
}

3.为抛出的异常编写文档

无论何时你的方法签名中只要有抛出异常,你应该在方法的Java文档中清晰地标注它们。这可以提示使用者去处理这些异常或者将它们再次抛出。
所以,必须在Java docs中使用@throws标注你的方法所抛出的所有异常。

/**
 * This method does something extremely useful ...
 *
 * @param input
 * @throws MyBusinessException if ... happens
 */
public void doSomething(String input) throws MyBusinessException {
    ...
}

Post Author: flygoxc

发表评论

电子邮件地址不会被公开。 必填项已用*标注