前言
在运行程序时进行 I/O 操作(如读取文件)后如果不关闭,那么进程就会一直占用该资源造成内存泄漏,特别是进行写操作,操作系统还会对该文件上锁,导致其他进程无法对该文件操作。因此,对资源 I/O 操作要记得进行 close()
。
try-finally
在 Java 代码里,读取文件操作如下:
public static void file() throws IOException {
Path pom = Paths.get("pom.xml");
BufferedReader bufferedReader = null;
try {
bufferedReader = Files.newBufferedReader(pom);
bufferedReader.lines().forEach(System.out::println);
} finally {
if (bufferedReader != null) {
bufferedReader.close();
}
}
}
对文件的关闭操作是在 finally
代码块里,防止异常导致文件没有 close()
。对该 .class
文件进行反编译,生成的代码差不多,这里就不展示了。
接下来我们看看 try-with-resources 是怎么写的。
try-with-resources
public static void file() throws IOException {
Path pom = Paths.get("pom.xml");
try (BufferedReader bufferedReader = Files.newBufferedReader(pom)) {
bufferedReader.lines().forEach(System.out::println);
}
}
看上去代码简洁了很多,少了 finally
代码块,接下来我们对该 .class
文件进行反编译:
public static void file() throws IOException {
Path pom = Paths.get("pom.xml");
BufferedReader bufferedReader = Files.newBufferedReader(pom);
Throwable var2 = null;
try {
Stream var10000 = bufferedReader.lines();
PrintStream var10001 = System.out;
var10000.forEach(var10001::println);
} catch (Throwable var11) {
var2 = var11;
throw var11;
} finally {
if (bufferedReader != null) {
if (var2 != null) {
try {
bufferedReader.close();
} catch (Throwable var10) {
var2.addSuppressed(var10);
}
} else {
bufferedReader.close();
}
}
}
}
可以发现,try-with-resources 所生成的代码比上面写的代码严谨很多,最终 close()
方法的调用也是在 finally
代码块里。
总结
程序的 I/O 操作尽量使用 try-with-resources,也可以防止忘记关闭资源。