You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)任务后立即关闭?

问题解答

  1. 这类流会被GC自动关闭吗?
    不会。GC仅负责回收无引用对象的内存空间,不会主动调用流的close()方法。早期部分流的finalize()方法会在对象回收前触发关闭,但该机制本身不可靠(GC执行时机不确定,Java 9后finalize()已被废弃),依赖它可能导致资源泄漏或数据丢失。

  2. 会在return时自动关闭吗?
    不会。return仅完成方法执行并返回结果,不会触发任何流的关闭逻辑。流的关闭必须显式调用close(),或通过try-with-resources语法自动处理。

  3. 还是在完成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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 22:18:29