Java7 中的 try-with-resources 结构是一种异常处理机制,它会在使用完 InputStream 或 JDBC Connection 等资源后自动关闭这些资源。因此,你必须在 Java try-with-resources 块中打开并使用资源。当执行离开 try-with-resources 代码块时,在 try-with-resources 代码块内打开的任何资源都会自动关闭(在也不需要在 finally 语句块中手动编写资源释放的重复代码)。
⚠️注意:无论 try-with-resources 代码块内或尝试关闭资源时是否抛出了异常,try-with-resources 都会自动释放资源,保证资源被正确释放。
要了解 Java try-with-resources 结构是如何工作的,先让我们来看一个简单的示例:
package com.hxstrive.jdk7.try_with_resources; import java.io.FileInputStream; /** * JDK7 新特性 try-with-resources * @author hxstrive.com */ public class TryWithResourcesDemo1 { public static void main(String[] args) throws Exception { try(FileInputStream input = new FileInputStream("D:\\test.txt")) { int data = input.read(); while(data != -1){ System.out.print((char) data); data = input.read(); } } } }
上面的 try-with-resources 示例展示了如何在 try-with-resources 块内打开 FileInputStream,然后从 FileInputStream 中读取一些数据,并在执行离开 try-with-resources 块后自动关闭 FileInputStream。
请注意,上述示例中方法内部的第一行代码:
try(FileInputStream input = new FileInputStream("D:\\test.txt")) {
这就是 try-with-resources 结构。在 try 关键字后的括号内声明了 FileInputStream 变量。此外,FileInputStream 将被实例化并分配给该变量。
当 try 代码块结束时,FileInputStream 将自动关闭。这是如何实现的呢?这是因为 FileInputStream 实现了 Java 接口 java.lang.AutoCloseable,如下图:
⚠️注意:所有实现 java.lang.AutoCloseable 接口的类都可以在 try-with-resources 结构中使用。
在 Java9 之前,必须在 try-with-resources 结构的 try 块的括号内创建要自动关闭的资源。从 Java9 开始,这不再是必须的了。如果引用资源的变量实际上是最终变量,您只需在 try 代码块的括号内输入对该变量的引用即可。例如:
package com.hxstrive.jdk9.try_with_resources; import java.io.FileInputStream; /** * JDK9 try-with-resources 增强 * @author hxstrive.com */ public class TryWithResourcesDemo1 { public static void main(String[] args) throws Exception { FileInputStream input = new FileInputStream("D:\\test.txt"); try(input) { int data = input.read(); while(data != -1){ System.out.print((char) data); data = input.read(); } } // 将抛出如下异常: // Exception in thread "main" java.io.IOException: Stream Closed System.out.println("char=" + (char)input.read()); } }
⚠️注意:input 变量已在 try 代码块外声明并分配了 FileInputStream(请留意 input 变量是如何在 try 代码块的括号内引用的)。这样,一旦退出 try 代码块,Java 仍会正确关闭 input 变量指向的 FileInputStream。当我们在 try 代码块外从 input 中读取数据,将抛出“java.io.IOException: Stream Closed”异常信息,说明流确实已经被自动关闭了。