本文参考

本篇文章参考自《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,这样得到的代码将更加简洁、清晰,产生的异常也更有价值

Effective Java —— try-with-resources 优先于 try-finally的更多相关文章

  1. [Effective Java]第八章 通用程序设计

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  2. EFFECTIVE JAVA 第十一章 系列化

    EFFECTIVE  JAVA  第十一章  系列化(将一个对象编码成一个字节流) 74.谨慎地实现Serializable接口 *实现Serializable接口付出的代价就是大大降低了“改变这个类 ...

  3. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

  4. 《Effective Java(中文第二版)》【PDF】下载

    <Effective Java(中文第二版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382186 Java(中文第二版)& ...

  5. 《Effective Java》 学习笔记 —— 并发

    <Effective Java>第二版学习笔记之并发编程. 第66条 同步访问共享的可变数据 * 关键字synchronized可以保证在同一时刻只有一个线程可以执行某个方法或代码块. * ...

  6. [Java读书笔记] Effective Java(Third Edition) 第2章 创建和销毁对象

      第 1 条:用静态工厂方法代替构造器 对于类而言,获取一个实例的方法,传统是提供一个共有的构造器. 类可以提供一个公有静态工厂方法(static factory method), 它只是一个返回类 ...

  7. 《Effective Java》笔记45-56:通用程序设计

    将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性. 要使用局部变量的作用域最小化,最有力的方法就是在第一次使用它的地方才声明,不要过早的声明. 局部变量的作用域从它被声明的 ...

  8. effective java 学习心得

    目的 记录一下最主要学习心得,不然凭我这种辣鸡记忆力分分钟就忘记白看了... 用静态工厂方法代替构造器的最主要好处 1.不必每次都创建新的对象 Boolean.valueOf Long.valueOf ...

  9. effective java 读后感

    think in java  , effective java  这两本书一直都在java的生态圈中经久不衰.本来想着先翻过 think in java 这本大山,但是读到一半就放弃了.过长的篇幅,让 ...

随机推荐

  1. C#中default 、base 、this关键字用法简介

     C#中default关键字用法简介 default 关键字可在switch语句或泛型代码中使用.switch语句:指定默认标签.泛型代码:指定类型参数的默认值.对于引用类型为空,对于值类型为零swi ...

  2. python学习笔记:1、读取文本文件,按行处理

    需求源于 整理 时序报告.按照以前的思路 都是按行行的 进行处理 提取需要的信息,判断. 首先的操作应该是读取. python的读取 两个方法 (1) 通过readline()来进行读取 f = op ...

  3. GAN实战笔记——第六章渐进式增长生成对抗网络(PGGAN)

    渐进式增长生成对抗网络(PGGAN) 使用 TensorFlow和 TensorFlow Hub( TFHUB)构建渐进式增长生成对抗网络( Progressive GAN, PGGAN或 PROGA ...

  4. Qt:打印输出到控制台,类似C++的cout

    1. #include<qDebug> 2. qDebug<<"Hello,world!"; 补充,如果不是控制台文件,比如是窗口应用程序,需要在pro文件 ...

  5. c# 自定义控件-提示框(弹框)

    分带取消按钮和不带取消按钮的 调用方法: frmMessageBox frm = new frmMessageBox("提示", "数据连接失败,请重试!", ...

  6. python列表的操作(添加)

    1. 向列表里面加元素: 向python列表里面添加元素主要有三种方法: (1)append() append()对于列表的操作主要实现的是在特定的列表最后添加一个元素,并且只能一次添加一个元素,并且 ...

  7. 创建vue脚手架步骤

    一.在cmd配置npm淘宝镜像 npm config set registry https://registry.npm.taobao.org 二.仅第一次执行安装,安装好后关掉cmd后再开,这个时候 ...

  8. ASP.NET Core 6框架揭秘实例演示[22]:如何承载你的后台服务[补充]

    借助 .NET提供的服务承载(Hosting)系统,我们可以将一个或者多个长时间运行的后台服务寄宿或者承载我们创建的应用中.任何需要在后台长时间运行的操作都可以定义成标准化的服务并利用该系统来承载,A ...

  9. Java子类继承父类的执行顺序

    父类的静态代码块(static) 子类的静态代码块(static) 父类的非静态代码块(父类成员初始化) 父类的构造方法 子类的非静态代码块(子类成员初始化) 子类的构造方法

  10. ArcMap操作随记(1)

    1.用python代码,将属性表中属性进行合并 代码:'ID'+str(!FID!) 2.地类编码与地类的转换 以python为例 显示代码块(预逻辑脚本代码): def getType(value) ...