使用传统的方式关闭流资源当然没问题,但是需要写的代码有点多,而
try-with-resources
是Java 7 之后的新语法糖,旨在减轻开发人员释放try块中使用的资源的压力。一时用TWR方式一时爽,一直用一直爽,但是有些情况也是不能使用这种方式的,但是绝大多数时候是可以使用的,下面进行详细的介绍。
传统方式关闭资源
这里以拷贝一个文件为例,我们最后需要关闭文件输入流和文件输出流。使用传统方式关闭如下:
@Test
public void copyFileWithClassics(){
/**
* 1、创建输入输出流
* 2、拷贝文件
* 3、关闭输入输出流
*/
String src = "src/strategy/demo/TWRDemo.java";
String dest = "src/strategy/demo/TWRDemo.java.bak";
// 1、创建输入输出流
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(src);
fileOutputStream = new FileOutputStream(dest);
// 2、拷贝文件
int content;
while ((content = fileInputStream.read()) != -1){
fileOutputStream.write(content);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
// 3、关闭输入输出流,遵循先打开后关闭原则
try{
if (fileOutputStream != null){
fileOutputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
if (fileInputStream != null){
fileInputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
可以看见,关闭输入输出流的时候需要判空和捕获IO异常,这样写当然没啥大问题,但是代码量是非常多的。那么在JDK7之后,可以使用TWR方式来关闭资源,如下。
Try-With-Resources 方式关闭资源
try-with-resources
是 Java
中用于自动资源管理的语句。它被设计用于在不再需要时自动关闭文件、套接字或数据库连接等资源,并通过减少样板代码来简化资源管理。具体做法就是将需要自动关闭资源的对象定义在try
后面的小括号中,注意:需要在小括号中声明!
@Test
public void copyFileWithTWR(){
/**
* 1、创建输入输出流
* 2、拷贝文件
* 3、自动关闭输入输出流
*/
String src = "src/strategy/demo/TWRDemo.java";
String dest = "src/strategy/demo/TWRDemo.java.bak";
// 1、创建输入输出流
try (
// 3、自动关闭输入输出流
FileInputStream fileInputStream = new FileInputStream(src);
FileOutputStream fileOutputStream = new FileOutputStream(dest);
){
// 2、拷贝文件
int content;
while ((content = fileInputStream.read()) != -1){
fileOutputStream.write(content);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
大多数JDK提供的流资源都可以使用TWR
方式自动关闭,但是有些情况下不能使用,下面这几种情况请注意不能使用TWR
方式:
- 不是 AutoCloseable 或 Closeable 接口的资源: try-with-resources 只能用于实现了 AutoCloseable 或 Closeable 接口的对象。如果一个资源没有实现这两个接口中的任何一个,就无法使用 try-with-resources。
// 如果 MyResource 没有实现 AutoCloseable 或 Closeable,将无法编译通过
try (MyResource resource = new MyResource()) {
// 使用资源的代码
} catch (Exception e) {
// 处理异常
}
- 在 try-with-resources 语句之外声明的资源: 在 try-with-resources 中使用的资源必须是 effectively final 或 final。如果尝试在 try-with-resources 块内为资源赋予新值,将无法编译。
// 由于 `resource` 不是 effectively final,所以这段代码将无法编译
MyResource resource = new MyResource();
try (resource) {
// 使用资源的代码
} catch (Exception e) {
// 处理异常
}
因此,在不确定是否会自动关闭资源的时候,请鼠标选中需要关闭的资源类名,然后快捷键 ctrl+H
快速查看继承关系,例如查看FileInputStream
如下:
可以看见最底层的实现接口是 AutoCloseable
,因此可以使用TWR方式关闭该资源!