Java IO资源能否自动关闭?try-with-resources使用及资源关闭确认
好问题!咱们一步步把这些疑问拆解清楚:
1. Java IO资源会不会自动关闭?
默认情况下不会。Java的IO资源(比如各种流、Reader/Writer)都需要显式调用close()方法来释放底层资源(比如文件句柄、网络连接)。如果不手动关闭,这些资源会被JVM的垃圾回收机制在某个不确定的时间点回收,但这会导致资源泄漏,尤其是在频繁操作IO的场景下,可能会耗尽系统资源。
不过从Java 7开始,引入了try-with-resources语句,只要资源类实现了AutoCloseable接口(Java IO类基本都实现了),就可以在try块中声明,JVM会自动在代码块执行完毕(正常结束或抛出异常)后调用资源的close()方法,无需手动处理。
2. 嵌套流在try-with-resources中会被连锁关闭吗?
你给出的读取文件代码是完全安全的:
try(final BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset))) { String line = null; while((line = br.readLine()) != null) { builder.append(line); } }
当BufferedReader被try-with-resources自动关闭时,它的close()方法会自动调用它所包装的InputStreamReader的close(),而InputStreamReader的close()又会调用底层FileInputStream的close()。这是Java IO流的设计规范:所有包装流的close()方法都会传递调用到内层被包装的资源,确保整个流链的资源都被释放。
所以哪怕你只在try-with-resources中声明最外层的BufferedReader,内层的InputStreamReader和FileInputStream也会被正确关闭,不需要单独声明。
3. 写入文件的嵌套流场景同理吗?
假设你的写入代码是类似这样的嵌套结构:
try(final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)))) { bw.write("some content"); }
答案是肯定的:外层BufferedWriter关闭时,会连锁调用OutputStreamWriter和FileOutputStream的close()方法,所有资源都会被正确释放。
额外提醒
虽然嵌套流会被连锁关闭,但如果你的代码中需要单独操作某个内层流(比如中途要重新打开或调整),那最好把每个资源都单独声明在try-with-resources中,用分号分隔:
try(final FileInputStream fis = new FileInputStream(file); final InputStreamReader isr = new InputStreamReader(fis, charset); final BufferedReader br = new BufferedReader(isr)) { // 操作代码 }
这种写法更清晰,也能避免某些极端情况下的资源泄漏(虽然嵌套写法在标准IO类中是安全的)。
内容的提问来源于stack exchange,提问作者tobiasbriones

