龙空技术网

丑拒!你还在这样操作Java I/O流?

小码哥Rick 975

前言:

当前看官们对“java 关闭流顺序”大致比较关切,你们都想要了解一些“java 关闭流顺序”的相关内容。那么小编也在网络上汇集了一些关于“java 关闭流顺序””的相关知识,希望姐妹们能喜欢,兄弟们快快来了解一下吧!

你是否也在这样操作输入和输出流?

话不多说,先上代码。如下所示是一个在我们项目中引用众多的工具类方法,方法功能也非常简单,就是将源路径的gzip压缩包解压到目标路径。

解压gzip压缩包工具方法

这段代码乍一看好像也没什么问题,因为你完全可以在网上搜索到许多类似的写法,这些代码中都毫无疑问地使用了try-catch-finally结构,也非常一致地在同一个finally代码块中关闭输入输出流并捕获异常。那对此还是摸不着头脑的人就要问了,这样写难道有问题吗?

你可能未意识到的问题大多数初学者都谨记了要最终关闭流,却未思考过关闭流的正确时机,假设如上代码中的FileInputStream创建失败且抛出异常,流程将直接进入catch分支,也就没必要调用close方法,finally子句中其实做了无谓的判断;若FileInputStream创建成功,那么后续所有的操作不管成功与否都应该最终调用其close方法;我们都知道使用finally的目的就是其中的语句一定会执行,但是对于我们所创建的每个流来说,关闭的正确时机并不统一;大多数人都知道try-catch-finally结构和try-catch结构,却不知道try-finally也是独立的结构;是该抛出还是捕获异常,许多开发者并没有真正搞清楚,对于一个通用的工具方法来说,我们更希望问题能够暴露出来而不是在内部被掩盖;判断输入输出流的操作是否执行成功本质上还是一种业务判断,并且只能通过捕获异常的方式来进行,那么是不是提到业务层来进行会更好。另外一种进阶但“丑陋”的写法

知道了关闭流的正确时机,我们可以使用try-finally对代码进行优化,优化后的方法如下,虽然如下代码在结构上好像是“无限套娃”,依然十分“丑陋”,但却是旧有模式下的最正确形式。

try-finally优化后的方法

try-with-resources的终极写法

虽然try-with-resources已经是Java SE 7的产物了,但是时至今日,我所共事过的许多从事Java开发的同事仍然不知道这个结构,当然更不会想到使用它。这个结构的作用也很简单,就是简化try-finally中关闭流的操作。如下的代码就是使用了该结构和工具类优化后的结果,当去除了手动close的代码之后,整体上已经不那么臃肿了,但是结构上依然存在“无限套娃”的问题,这样写当然不影响正确执行,却也不够简洁美观。

try-with-resources处理单个资源写法

那如何解决这个问题呢,其实try-with-resources是可以处理多个资源的,资源声明的顺序就是初始化的顺序,而关闭的顺序正与此相反。

最终优化后的代码如下,与最初的代码相比是不是已经彻底地改头换面了呢。

try-with-resources处理多个资源写法

标签: #java 关闭流顺序