本文参考

本篇文章参考自《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. 如何处理大体积 XLSX/CSV/TXT 文件?

    在开发过程中,可能会遇到这样的需求,我们需要从本地的 Excel 或 CSV 等文件中解析出信息,这些信息可能是考勤打卡记录,可能是日历信息,也可能是近期账单流水.但是它们共同的特点是数据多且繁杂,人 ...

  2. containerd与kubernetes集成部署

    概念介绍 cri (Container runtime interface) cri is a containerd plugin implementation of Kubernetes conta ...

  3. Oracle之SQL限定查询

    WHERE限定条件 /*语法结构:SELECT * | 列名1[,列名2...] | 表达式FROM 表名 WHERE 限定条件; */ --查询职位为CLERK的员工信息 SELECT * FROM ...

  4. Visual Studio 文字样式背景设置

    菜单栏 "工具"->选项->环境->常规

  5. ValueError: not enough values to unpack

    当在同一行为两个变量赋值时,要用分号;而非逗号,隔开

  6. Flask 自建扩展

    自建扩展介绍 Flask扩展分两类 纯功能, 如: Flask-Login 提供用户认证 对已有的库和工具包装(简化继承操作,并提供有用的功能,更方便) 如: Flask-SQLAlchemy 包装了 ...

  7. php 修改后端代码参考

    后端代码参考:

  8. laravel7 搜索分页

    html: <form action="{{url('http://www.yanbing.com/fang/index')}}" method="get" ...

  9. 谈谈对mvc 的认识?

    由模型(model),视图(view),控制器(controller)完成的应用程序由模型发出要实现的功能到控制器,控制器接收组织功能传递给视图;MVC 是一个设计模式,它强制性的使应用程序的输入.处 ...

  10. git常用命令及问题

    Git基本操作 git init 创建新的git仓库 git clone [url] 使用 git clone 拷贝一个 Git 仓库到本地 git status 查看工作区 git stash li ...