首页 > 代码库 > try-with-resources语句
try-with-resources语句
这节讲的是Java7中引入的使用try语句进行资源管理的新用法。这节的内容与上一节介绍的异常处理的关系比较密切。上节中介绍的Throwable中的新方法addSuppressed就是为try-with-resourcces语句添加的。对于资源管理,大多数开发人员都知道的一条原则是:谁申请,谁释放。这些资源涉及操作系统中的主存、磁盘文件、网络连接和数据库连接等。凡是数量有限的、需要申请和释放的实体,都应该纳入到资源管理的范围中来。
在使用资源的时候,有可能会抛出各种异常,比如读取磁盘文件和访问数据库时都可能出现在各种不同的异常。而资源管理的一个要求就是不管操作是否成功,所申请的资源都要被正确释放。上一节中我们有比较典型的资源释放的示例,这里我们要讲一讲java7中对资源管理的增强。Java7中对try语句进行了增强,使它可以支持对资源进行管理,保证资源总是被正确释放。如例:
package test; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class ResourceBasicUsage { public String readFile(String path) throws IOException { try(BufferedReader reader = new BufferedReader(new FileReader(path))) { //注意这里 StringBuilder builder = new StringBuilder(); String line = null; while((line = reader.readLine()) != null){ builder.append(line); builder.append(String.format("%n")); } return builder.toString(); } } public static void main(String[] args) { ResourceBasicUsage usage = new ResourceBasicUsage(); try { System.out.println(usage.readFile("F:/manifest_provider_loophole.txt")); } catch (IOException e) { e.printStackTrace(); } } }
上面的代码并不需要使用finally语句来保证打开的流被正确关闭,这是自动完成的。相对于传统的使用finally语句的做法,这种方式简单得多。开发人员只需要关心使用资源的业务逻辑即可。资源的申请是在try子句中进行的,而资源的释放是自动完成的。在使用try-with-resources语句的时候,异常可能发生在try语句中,也可能发生在释放资源时。如果资源初始化时或try语句中出现异常,而释放资源的操作正常执行,try语句中的异常会被抛出。如果try语句和释放资源都出现了异常,那么最终抛出的异常是try语句中出现的异常,在释放资源时出现的异常会作为被抑制的异常添加进去,即通过Throwable.addSuppressed方法来实现。
能够被try语句所管理的资源需要满足一个条件,那就是其java类要实现java.lang.AutoCloseable接口,否则会出现在编译错误。当需要释放资源的时候,该接口的close方法会被自动调用。Java类库中已有不少接口或类继承或实现了这个接口,使得它们可以用在try语句中。在这些已有的常见接口或类中,最常用的就是与I/O操作和数据库相关的接口。与I/O相关的java.io.Closeable继承了AutoCloseable,而与数据库相关的java.sql.Connection、java.sqlResultSet和java.sql.Statement也继承了该接口。如果希望自己开发的类也能利用try语句的自动化资源管理,只需要实现AutoCloseable接口即可。
除了对单个资源进行管理之外,try-with-resources还可以对多个资源进行管理。如例:
package test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class MultipleResourcesUsage { public void copyFile(String fromPath,String toPath) throws IOException { try(InputStream input = new FileInputStream(fromPath); //注意,这里用了分号 OutputStream output = new FileOutputStream(toPath)){ byte[] buffer = new byte[8192]; int len = -1; while((len = input.read(buffer)) != -1){ output.write(buffer, 0, len); } } } public static void main(String[] args) { MultipleResourcesUsage usage = new MultipleResourcesUsage(); try { usage.copyFile("F:/manifest_provider_loophole.txt", "F:/aaa.txt"); } catch (IOException e) { e.printStackTrace(); } } }
当对多个资源进行管理的时候,在释放每个资源时都可能会产生异常。所有这些异常都会被加到资源初始化异常或try语句块中抛出的异常的被抑制异常列表中。
在try-with-resource语句中也可以使用catch和finally子句。在catch子句中可以捕获try语句块和释放资源时可能发生的各种异常。
try-with-resources语句