关于异常处理的随记(更)

1. 在 finally 块中清理资源或者使用 try-with-resource 语句

当使用类似InputStream这种需要使用后关闭的资源时,一个常见的错误就是在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 代码块内代码会正常执行,并且资源可以正常关闭。
  • 但是,使用 try 代码块是有原因的,一般调用一个或多个可能抛出异常的方法,而且,你自己也可能会抛出一个异常,这意味着代码可能不会执行到 try 代码块的最后部分。结果就是,并没有关闭资源。
  • 所以,应该把清理工作的代码放到 finally 里去,或者使用 try-with-resource 特性。

    1.1 使用 finally 代码块

  • 与前面几行 try 代码块不同,finally 代码块总是会被执行。不管 try 代码块成功执行之后还是你在 catch 代码块中处理完异常后都会执行。因此,可以确保你清理了所有打开的资源。
    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);
              }
          }
      }
    }

    1.2 Java 7 的 try-with-resource 语法

  • 如果资源(类)实现了 AutoCloseable 接口,可以使用这个语法。大多数的 Java 标准资源都继承了这个接口。当在 try 子句中打开资源,资源会在 try 代码块执行后或异常处理后自动关闭。
    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);
      }
    }
    缺陷是: try..catch..之后无法再使用此资源。
    此外,JDK1.9之后 支持在try(括号中多个资源用逗号隔开)

2. 优先明确的异常

  • 抛出的异常越明确越好。
  • 需要保证提供给他人尽可能多的信息。这样你的 API 更容易被理解。你的方法的调用者能够更好的处理异常并且避免额外的检查。
    因此,总是尝试寻找最适合你的异常事件的类,例如,抛出一个 NumberFormatException 来替换一个 IllegalArgumentException 。避免抛出一个不明确的异常。
    public void doNotDoThis() throws Exception {
      ...
    }
    public void doThis() throws NumberFormatException {
      ...
    }

3. 不要使用异常控制程序的流程

  • 不应该使用异常控制应用的执行流程,例如,本应该使用if语句进行条件判断的情况下,你却使用异常处理,这是非常不好的习惯,会严重影响应用的性能。

4. 尽量使用标准异常!!

  • 如果使用内建的异常可以解决问题,就不要定义自己的异常。Java API 提供了上百种针对不同情况的异常类型,在开发中首先尽可能使用 Java API 提供的异常,如果标准的异常不能满足你的要求,这时候创建自己的定制异常。尽可能得使用标准异常有利于新加入的开发者看懂项目代码。
全部评论

相关推荐

有趣的牛油果开挂了:最近这个阶段收到些杂七杂八的短信是真的烦
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务