Java try-with-resources 结构是在 Java 7 中添加的。在 Java 7 之前,管理需要显式关闭的资源有些繁琐。您必须手动处理资源的正确关闭。要正确处理这项任务并不容易。要了解原因,请参阅下面的方法,该方法读取文件并将其打印到 System.out.RTF 中:
package com.hxstrive.jdk7.try_with_resources;
import java.io.FileInputStream;
import java.io.InputStream;
/**
* JDK7 新特性 try-with-resources
* @author hxstrive.com
*/
public class TryWithResourcesDemo13 {
public static void main(String[] args) throws Exception {
InputStream input = null;
try {
input = new FileInputStream("D:\\test.txt"); // 可能会出错,文件不存在
int data = input.read(); // 读取可能会出错
while(data != -1){
System.out.print((char) data);
data = input.read(); // 读取可能会出错
}
} finally {
if(input != null){
input.close(); // 关闭资源,也可能会出错
}
}
}
}正如上面,异常可能发生在 try 代码块中的 3 个地方,以及 finally 代码块中的 1 个地方。
无论 try 代码块是否抛出异常,finally 代码块都会被执行。这意味着,无论 try 代码块中发生了什么,InputStream 都会被关闭。或者说,试图关闭。如果关闭失败,InputStream 的 close() 方法也会抛出异常。
试想一下,异常是从 try 代码块内部抛出的。然后执行 finally 代码块。再假设 finally 代码块也抛出了异常。你认为哪个异常会在调用栈中向上传播?例如:
package com.hxstrive.jdk7.try_with_resources;
import java.io.FileInputStream;
import java.io.InputStream;
/**
* JDK7 新特性 try-with-resources
* @author hxstrive.com
*/
public class TryWithResourcesDemo14 {
public static void main(String[] args) throws Exception {
InputStream input = null;
try {
input = new FileInputStream("D:\\test.txt"); // 可能会出错
int data = input.read(); // 可能会出错
while(data != -1){
System.out.print((char) data);
data = input.read(); // 可能会出错
}
System.out.println();
throw new Exception("try exception");
} finally {
if(input != null){
input.close(); // 关闭资源,也可能会出错
}
throw new Exception("finally exception");
}
//结果:
//You have to believe in yourself. That's the secret of success. Charles Chaplin
//Genius is one percent inspiration and ninety-nine percent perspiration. Thomas Edison
//Exception in thread "main" java.lang.Exception: finally exception
// at com.hxstrive.jdk7.try_with_resources.TryWithResourcesDemo14.main(TryWithResourcesDemo14.java:28)
}
}从上例可知,从 finally 代码块中抛出的异常会被上传到调用堆栈,即使从 try 代码块中抛出的异常可能更适合上传到调用堆栈。