Tip:该新特性可以解决代码质量测试工具Sonarqube的try-catch资源检查抛出来的异常
本文章以IO流先行简单举例说明,后续反编译JDBC连接池说明该特性的自动关闭顺序
在JDK1.7之前我们对资源的关闭都是这样来实现的,如下图。
就是在try-catch-finally代码块外围定义资源对象,try块里面进行实例化调用,最终finally里面进行关闭(释放)资源。多出一个finally块来处理资源关闭会让代码看着很多,尤其是这个IO的操作,fileReader的close方法还会抛出一个异常就还得来一个catch捕获,虽然可读性没啥问题了。
然后,在JDK1.7新引申出来一个自动管理资源的解决方案,让这些资源不必再去finally里面手动关闭了。
详情可以参考Oracle官方文档:Java Programming Language Enhancements (oracle.com)
改良后的代码如下:
对比1.7之前的代码去除了finally手动关闭资源的内容,而将这一资源放到了try块后面新增加的括号中。如此即可实现自动关闭(释放)资源。
现在说一下资源关闭顺序
首先看一下官方文档上的说辞,如下图。
也就是说它的关闭顺序是跟我们在括号中编写的代码顺序反着来的,那我们来看一下是否确实如此。首先编写一段基本的JDBC连接操作数据库的代码,如下图(红圈括起来的位置就是我们要关注的点)。
按正常的关闭流程来讲的话,是应该将这段资源从下到上来进行关闭的,而官方文档也提到了是反着来关的,那我们拿这段代码反编译一波来看一下。
我这里拿cmd窗口最大化截了个图,正好能看到这三个关闭方法。从红圈里的内容来看这个自动资源管理确实是按照括号里的顺序反着来关闭的,这样也正好能符合我们平时的资源关闭顺序。
这里附上我的JDBC这一段代码,有兴趣的话可以改成自己的数据库信息自行测试一波(拿这段代码直接放到main方法中并修改成自己的连接信息即可运行)。
```java
```java
```java
long start = System.currentTimeMillis();
//加载MySql的驱动类
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("找不到驱动程序类 ,加载驱动失败!");
e.printStackTrace();
}
String url = "jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8";
String username = "root";
String password = "root";
try (Connection con = DriverManager.getConnection(url, username, password);
Statement statement = con.createStatement();
ResultSet resultSet = statement.executeQuery("select * from text_test where id = 2")) {
String text = null;
while (resultSet.next()) {
text = resultSet.getString(2);
}
assert text != null;
System.out.println(formatJSONString(text));
} catch (SQLException se) {
System.out.println("数据库连接失败!");
se.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println((end - start) + "ms");
该文章仅供参考,如有错误或缺漏欢迎各位指点迷津。