Java中未赋值给对象的流会自动关闭吗?多场景疑问解答
Java序列化深拷贝中流自动关闭的疑问
我正在学习Java,尝试编写一个基于序列化实现深拷贝的类:
public class SerialDeepCopier<T extends Serializable> { public T deepCopy(T origin) throws Exception{ ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(); ObjectOutputStream oStream = new ObjectOutputStream(writeBuffer); oStream.writeObject(origin); ByteArrayInputStream readBuffer = new ByteArrayInputStream(writeBuffer.toByteArray()); ObjectInputStream iStream = new ObjectInputStream(readBuffer); T returnValue = (T) iStream.readObject(); /* CLOSE THE STREAMS */ writeBuffer.close(); oStream.close(); readBuffer.close(); iStream.close(); return returnValue; } }
我知道使用完流后手动关闭是最佳实践,但发现不保存流实例引用的写法也能运行:
ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(); new ObjectOutputStream(writeBuffer).writeObject(origin);
这种写法下无法手动调用close(),因此有以下疑问:
- 这类流会被GC自动关闭吗?
- 会在return时自动关闭吗?
- 还是在完成writeObject(origin)任务后立即关闭?
问题解答
这类流会被GC自动关闭吗?
不会。GC仅负责回收无引用对象的内存空间,不会主动调用流的close()方法。早期部分流的finalize()方法会在对象回收前触发关闭,但该机制本身不可靠(GC执行时机不确定,Java 9后finalize()已被废弃),依赖它可能导致资源泄漏或数据丢失。会在return时自动关闭吗?
不会。return仅完成方法执行并返回结果,不会触发任何流的关闭逻辑。流的关闭必须显式调用close(),或通过try-with-resources语法自动处理。还是在完成writeObject(origin)任务后立即关闭?
不会。writeObject()仅完成对象序列化的写入操作,不会自动关闭流。此时流对象仍存在于内存中,只是没有被引用,直到GC回收它之前,始终处于未关闭状态。
优化建议
虽然ByteArrayOutputStream是内存流,关闭它不会占用系统资源,但ObjectOutputStream的close()会触发缓冲区刷新,确保所有序列化数据写入底层流。养成规范的流处理习惯,能避免后续更换为文件流等资源型流时出现泄漏问题。
推荐使用try-with-resources语法,它会自动关闭所有实现AutoCloseable接口的资源,代码更简洁安全:
public class SerialDeepCopier<T extends Serializable> { public T deepCopy(T origin) throws Exception { try (ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(); ObjectOutputStream oStream = new ObjectOutputStream(writeBuffer)) { oStream.writeObject(origin); try (ByteArrayInputStream readBuffer = new ByteArrayInputStream(writeBuffer.toByteArray()); ObjectInputStream iStream = new ObjectInputStream(readBuffer)) { return (T) iStream.readObject(); } } } }
内容的提问来源于stack exchange,提问作者Naughtless
相关产品推荐
相关产品推荐

