• Effective Java —— try-with-resources 优先于 try-finally


    本文参考

    本篇文章参考自《Effective Java》第三版第九条"Prefer try-with-resources to try-finally"

    The code in both the try block and the finally block is capable of throwing exceptions.The second exception(in finally block) can completely obliterate the first one

    try块和finally块都有可能抛出异常,若同时抛出异常,则finally块中的第二个异常将会覆盖try块的异常,使我们无法追踪到程序错误的根源,例如下面这段代码示例

    @Test
    public void tryFinallyTest() throws Exception {
      try {
        throw new Exception("try block Exception");
      } finally {
        throw new Exception("finally block Exception");
      }
    }

    从执行结果中可以看出,try块中的异常没有显示

    下面是一个更加实际的例子,BufferReader的readLine()方法和close()方法都会抛出IoException异常,close()抛出的异常可能会覆盖readLine()方法的异常

    public void tryFinallyTest(String path) throws IOException {
      BufferedReader reader = new BufferedReader(new FileReader(path));
      try {
        System.out.println(reader.readLine());
      } finally {
        reader.close();
      }
    }

    我们可以通过catch块捕获try块内的异常,这样finally块的异常就不会覆盖try块的异常

    但是这未免有点"奇怪",因为当我们为方法加上throws Exception时,希望方法内产生的异常交由调用方或更上一级去处理,而不是在方法内部处理

    这样一来,try块的异常由方法内部处理,而finally块的异常由调用方或更上一级处理,增加了我们对异常捕获的管理难度

     

    Not only are the try-with-resources versions shorter and more readable than the originals, but they provide far better diagnostics

    自java7开始加入了try-with-resource语法并引入了AutoCloseable接口,只要相关资源的类或接口实现或继承了这个接口,就可以不显式调用close()方法,自动关闭资源,并且不会有上述"异常覆盖"的情况发生

    An object that may hold resources (such as file or socket handles) until it is closed. The close() method of an AutoCloseable object is called automatically when exiting a try-with-resources block for which the object has been declared in the resource specification header. This construction ensures prompt release, avoiding resource exhaustion exceptions and errors that may otherwise occur.

    我们同时用两种形式的try语句来进行测试,throwException()方法累计抛出的异常

    public class TryTest implements AutoCloseable {
      private int count = 0;

      @Test
      public void tryResourceTest() throws Exception {
        try(TryTest test = new TryTest()) {
          test.throwException();
        }
      }

      @Test
      public void tryFinallyTest() throws Exception {
        TryTest test = new TryTest();
        try {
          test.throwException();
        } finally {
          test.close();
        }
      }

      public void throwException() throws Exception {
        count++;
        throw new Exception("the No." + count + " Exception occurs");
      }

      @Override
      public void close() throws Exception {
        throwException();
      }
    }

    try-finally语句块的执行结果

    try-with-resources语句块的执行结果

    我们可以成功看到我们真正想要看到的第一个异常信息,第二个异常被标注为抑制

    In fact, multiple exceptions may be suppressed in order to preserve the exception that you actually want to see. These suppressed exceptions are not merely discarded; they are printed in the stack trace with a notation saying that they were suppressed. You can also access them programmatically with the getSuppressed method, which was added to Throwable in Java 7

    在try-with-resources语句块我们还是能够使用catch语句和finally语句,下面是一个更加实际的例子:

    public void copy(String src, String dst) {
      try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)) {
        byte[] buf = new byte[BUFFER_SIZE];
        int n;
        while ((n = in.read(buf)) >= 0) out.write(buf, 0, n);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    因此在处理必须关闭的资源时,我们始终要优先考虑用 try-with-resources,而不是用try-finally,这样得到的代码将更加简洁、清晰,产生的异常也更有价值

  • 相关阅读:
    堆排序算法(C#实现)
    在 .NET 2.0 中享受 .NET 3.0的特性
    火花:使用文件管理功能管理我的连接
    我们可以做的更好
    有价值的文章
    网上掏宝
    WPF绑定技术一步步学
    结构类型需要重载GetHashCode和Equals
    关于扩展Visual Studio 2005的相关资料
    插件模型应该考虑的问题
  • 原文地址:https://www.cnblogs.com/kuluo/p/12790648.html
Copyright © 2020-2023  润新知