Java 代码字节:足智多谋的 Try-With-Resources

当通过 Java 实现业务实例时,对资源进行处理是司空见惯的。一般情况下,资源(如文件或 socket 句柄)封装在对象中,使用后必须关闭才能释放资源。通常开发人员有责任关闭自己所创建的资源,以避免资源冲突,一般都会放在 finally 语句块中处理。不这样做其实也不会产生编译错误,但很容易导致资源泄露。虽然现在静态代码检查工具足够聪明,也可以做出提示。但不是每个人都使用工具,而且这些警告也容易被忽略。 Java 7 中首次引入了一种新的处理(关闭)资源的方式——try-with-resources。它使得在 try-catch 语句块中的资源能按照正确顺序自动关闭,更加容易地处理资源。 我们来一起看一个业务实例的实现,其需要从数据库中获取指定账户的状态码。首先可以看到它是如何以传统方式实现,紧接着是足智多谋的 try-with-resources 如何实现。最后,还将看到 Java 9 引入的更加简洁的版本。 传统的方式处理资源(Java 7 之前)

// 代码已简化,只保留跟眼下话题相关的内容。 public static int getAccountStatusCodeFromDataStore_traditional(String accountId) throws SQLException { String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId); Statement statement = null; ResultSet resultSet = null; try { statement = createStatementFromConnection(); resultSet = statement.executeQuery(accountStatusCodeQuery); return getAccountStatusCodeFromResultSet(resultSet); } finally { if (resultSet != null) resultSet.close(); if (statement != null) statement.close(); } }

如上所示,我们必须增加 finally 语句块来处理资源关闭。在调用 close 方法之前,须显示地检查 null 值,并且同时要保证关闭资源的逻辑顺序。代码不但变得冗长,而且我们曾经遇到过许多开发人员会忘记编写 finally 语句块来关闭资源,导致资源泄露的情况。 顺便提一下,假如 try 和 finally 语句块都抛出异常,finally 语句块抛出的异常会屏蔽对方。 Java 7/8 中通过 try-with-resources 处理资源 现通过 try-with-resources 实现与上面相同的代码块,如下所示:

// 代码已简化,只保留跟眼下话题相关的内容。 public static int getAccountStatusCodeFromDataStore_tryWithResourcesJava7(String accountId) throws SQLException { String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId); try (Statement statement = createStatementFromConnection(); ResultSet resultSet = statement.executeQuery(accountStatusCodeQuery)) { return getAccountStatusCodeFromResultSet(resultSet); } }

在本例中可以看到简洁的代码有助于提高整体可读性,资源管理也自动完成。try-with-resources 语句中可以包含多个资源,它们之间应通过分号隔开。资源会在保持逻辑顺序的前提下自动关闭(最后声明的将第一个关闭)。 如果在 try-with-resources 和 try 语句块中抛出异常,从 try 中抛出的异常将会屏蔽对方。假如有需要,可从 try 语句块抛出的异常中,通过调用 Throwable.getSuppressed 方法找回屏蔽的异常。 try-with-resources 语句中也可以写 catch 和 finally 语句块。任何 catch 和 finally 语句块会在声明的资源关闭后运行。 Java 9 中通过 try-with-resources 处理资源 Java 9 中引入了更加简练的版本。如果已经把资源声明为 final 或 effective final,则在 try-with-resources 中无需创建任何新的变量,可直接使用。这使得能够利用自动资源管理。现通过更简洁的 try-with-resources 语句来实现与上面相同的代码块,如下所示:

// 代码已简化,只保留跟眼下话题相关的内容。 public static int getAccountStatusCodeFromDataStore_tryWithResourcesJava9(String accountId) throws SQLException { String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId); // 显示地声明 final final Statement statement = createStatementFromConnection(); // effective final ResultSet resultSet = statement.executeQuery(accountStatusCodeQuery); try (statement; resultSet) { return getAccountStatusCodeFromResultSet(resultSet); } }

幕后如何运行 Java 7 引入了专门设计用于 try-with-resources 语句的 AutoCloseable 接口。Java 5 引入的 Closeable 接口也修改为继承 AutoCloseable 接口。这两个接口都拥有抽象的 close 方法,资源应该实现它并提供有效的方法。任何实现 AutoCloseable 和 Closeable 接口的资源都可以通过 try-with-resources 来关闭。所有基于 JDK 资源的类和接口都已修改成继承这两个接口其中之一,使之能与现有的 try-with-resources 语句兼容。 然而,若处理的资源没有实现 AutoCloseable 或 Closeable 接口,则必须使用传统的方法来关闭。 关键要点 try-with-resources 有助于自动资源管理,不需要编写显示的 finally 语句块来处理关闭资源。下面是对 try-with-resources 关键点的总结: 有助于实现简练清晰的代码。 可以在 try-with-resources 语句中同时处理多个资源。 在 Java 7/8 ,try-with-resources 语句中必须声明要关闭的资源。通过这种方式声明的资源属于隐式 final。 Java 9 中甚至能使用预先创建的资源,只要所引用的资源声明为 final 或者是 effective final。 在幕后施展魔法的是 AutoCloseable 或者 Closeable 接口,它们与 try-with-resources 语句协同工作。 JDK 中大多数基于资源的类和接口已修改成实现 AutoCloseable 或 Closeable 接口,使它们能与现有的 try-with-resources 兼容。 可以使自定义的资源实现 AutoCloseable 或 Closeable 接口,以便能够在 try-with-resources 语句中使用。 在这里给大家提供一个学习交流的平台,java架构师群: 867748702 具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。 在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。 如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的可以加群。


加Java架构师进阶交流群获取Java工程化、高性能及分布式、高性能、深入浅出。高架构。 性能调优、Spring,MyBatis,Netty源码分析和大数据等多个知识点高级进阶干货的直播免费学习权限 都是大牛带飞 让你少走很多的弯路的 群号是: 867748702对了 小白勿进 最好是有开发经验 注:加群要求 1、具有工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加。 2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加。 3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的,可以加。 4、觉得自己很牛B,一般需求都能搞定。但是所学的知识点没有系统化,很难在技术领域继续突破的可以加。 5.阿里Java高级大牛直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!

转载于:https://juejin.im/post/5bd94fde6fb9a02251128018

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值