try-with-resources语句是一种声明了一种或多种资源的try语句。资源是指在程序用完了之后必须要关闭的对象。try-with-resources语句保证了每个声明了的资源在语句结束的时候都会被关闭。任何实现了java.lang.AutoCloseable接口的对象,和实现了java.io.Closeable接口的对象,都可以当做资源使用。
 
下面的例子读取了一个文件的第一行。它使用了一个BufferedReader实例去读取文件,BufferedReader是一种资源,用完之后必须关闭。
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
在这个例子中,try-with-resources语句种声明的是BufferedReader资源。声明语句紧跟着在try关键词的圆括号里面。BufferedReader从Java SE7开始就实现了java.lang.AutoCloseable接口。因为BufferedReader声明在了try-with-resources里面,所以无论try语句是正常结束还是异常结束(比方说BufferedReader.readLine方法抛出一个IOException异常),它都会被关闭。
 
在Java SE7之前,你可以用finally代码块来确保资源一定被关闭,无论try语句正常结束还是异常结束。下面的例子用finally代码块代替try-with-resources语句:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
然而,在这个例子中,如果readLine和close方法都抛出异常,那么readFirstLineFromFileWithFinallyBlock方法最终会在finally代码块抛出异常,从try代码块里面抛出的那个异常被抑制住了。相比之下,readFirstLineFromFile方法中,如果try代码块和try-with-resources语句同时抛出异常,这个方法将会最终抛出try代码块里面的异常,try-with-resources语句里面抛出的异常被压抑了。在Java SE7之后,你可以找回被压抑的异常。参看后面的“被压抑的异常”部分。
 
你可以在一个try-with-resources语句里面声明多个资源。下面的例子展示了从一个名字为zipFileName的zip文件中检索出里面所有文件的名称,并创建一个文本文件存储所有文件名称。
 
public static void writeToFileZipFileContents(String zipFileName,
String outputFileName)
throws java.io.IOException { java.nio.charset.Charset charset =
java.nio.charset.StandardCharsets.US_ASCII;
java.nio.file.Path outputFilePath =
java.nio.file.Paths.get(outputFileName); // Open zip file and create output file with
// try-with-resources statement try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
// Enumerate each entry
for (java.util.Enumeration entries =
zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName =
((java.util.zip.ZipEntry)entries.nextElement()).getName() +
newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
}
在这个例子中,try-with-resources语句包含了两个用分号隔开的声明:ZipFile和BufferedWriter。当代码块中代码终止,不管是正常还是异常,BufferedWriter和ZipFile对象的close方法都会自动按声明的相反顺序调用。
 
下面的例子用try-with-resources语句自动关闭一个java.sql.Statement对象:
public static void viewTable(Connection con) throws SQLException {

    String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES";

    try (Statement stmt = con.createStatement()) {
ResultSet rs = stmt.executeQuery(query); while (rs.next()) {
String coffeeName = rs.getString("COF_NAME");
int supplierID = rs.getInt("SUP_ID");
float price = rs.getFloat("PRICE");
int sales = rs.getInt("SALES");
int total = rs.getInt("TOTAL"); System.out.println(coffeeName + ", " + supplierID + ", " +
price + ", " + sales + ", " + total);
}
} catch (SQLException e) {
JDBCTutorialUtilities.printSQLException(e);
}
}

这是我自己写的:

      /**
* 使用try-with-resources块改进异常处理代码
*/
public static void testExecuteQueryNew() {
try {
Class.forName(DRIVER_CLASS);
} catch (ClassNotFoundException e) {
// LOGGER.error("can not find driver class",e);
return;
}
try (Connection connection = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
PreparedStatement preparedStatement = connection.prepareStatement(SQL);
ResultSet resultSet = preparedStatement.executeQuery();
)
{ if (resultSet.next()) {
System.out.println(resultSet.getObject(1)+" : "+resultSet.getObject(2));
}
} catch (Exception e) {
e.printStackTrace();
}
}
例子中的资源java.sql.Statement是JDBC 4.1及其后面版本的一部分。
 
注意:try-with-resources语句也可以像普通的try语句一样,有catch和finally代码块。在try-with-resources语句中,任何的catch和finally代码块都在所有被声明的资源被关闭后执行。
 
被压抑的异常
 
try-with-resources语句相关联的代码块可能会抛出异常。在writeToFileZipFileContents例子中,try代码块中可能会抛出异常,并且有高达两个异常可能会在try-with-resources语句抛出,当试图去关闭ZipFile和BufferedWriter对象的时候。如果在try代码块中抛出一个异常,同时在try-with-resources语句中抛出一个或多个异常,那么在try-with-resources语句中抛出的异常就被压抑了,并且最终在writeToFileZipFileContents方法抛出的异常就是try代码块中抛出的那个异常。你可以通过被try代码块抛出的异常的Throwable.getSuppressed方法找回被压抑的异常。
 
实现了AutoCloseable或Closeable接口的类
 
看 AutoCloseable 和 Closeable 接口的javadoc,看看实现了它们的类都有哪些。Closeable接口继承了AutoCloseable接口。不同之处在于,Closeable接口的close方法抛出的是IOException异常,AutoCloseable接口的close方法抛出的是Exception异常。 因此,AutoCloseable的子类可以重写close方法的行为,抛出指定的异常,比如IOException异常,甚至可以不抛出异常。

最新文章

  1. Postman - 功能强大的 API 接口请求调试和管理工具
  2. 为什么很多SaaS企业级产品都熬不过第一年
  3. 在redis中使用lua脚本让你的灵活性提高5个逼格
  4. [BZOJ3224]Tyvj 1728 普通平衡树
  5. python 获取网页图片
  6. 【JavaEE企业应用实战学习记录】MyGetAttributeListener
  7. VS2013 解决方案文件结构分析
  8. [转]Linux read用法
  9. SQL Server 2008复制发布订阅(数据同步)
  10. 数往知来C#面向对象准备〈二〉
  11. SQL Server :事务和锁
  12. Struts2 全局拦截器、result 的实现
  13. 单源最短路径—Bellman-Ford和Dijkstra算法
  14. [转]Permission denied: /.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable
  15. 自动化脚本中click()或sendKeys()没有反应
  16. .NET CAD二次开发学习 直线画矩形并转换成组
  17. spark-sql缩减版样例:获取每日top3搜索词和各自的次数,包括总次数
  18. vim: 基本知识;
  19. 【转】Linux 虚拟内存和物理内存的理解
  20. mybatis 查询优化主子表查询之association和collection

热门文章

  1. STM32 时钟配置的坑
  2. windows下安装mongodb的崩溃史
  3. browser-cookies 一个管理cookies的插件,好用
  4. 日期插件Mobiscroll
  5. 成都Uber优步司机奖励政策(3月24日)
  6. SQLite FTS3/FTS4与一些使用心得
  7. hive读书笔记
  8. Ubuntu 14.04 登录 界面添加 root账号
  9. 用IDEA编写spark的WordCount
  10. 初学Direct X(8) ——碰撞检测