序列化会导致深度克隆?

时间:2011-09-23 13:01:35

标签: oop serialization cloneable

我正在阅读由ASF撰稿人撰写的文章,他简要地提到深度克隆对象的“旧Java技巧”是将其序列化,然后将其反序列化为另一个对象。当我读到这篇文章时,我停顿了一下,想到“嘿,这很聪明。”不幸的是,深度克隆或序列化都不是文章的主题,因此作者从未举出过他所谈论的内容的例子,而且在线搜索并未撤回任何内容。

我必须假设,我们正在谈论某事,如下所示:

public class Dog implements Serializable
{
    // ...

    public Dog deepClone()
    {
        Dog dogClone = null;
        try
        {
            FileOutputStream fout = new FileOutputStream("mydog.dat");
            ObjectOutputStream oos = new ObjectOutputStream(fout);
            oos.writeObject(this);
            oos.close();

            FileInputStream fin = new FileInputStream("mydog.dat");
            ObjectInputStream ois = new ObjectInputStream(fin);
            dogClone = (Dog)ois.readObject();
            ois.close();

            return dogClone;
        }
        catch(Exception e)
        { 
            // Blah
        }
    }

如果我可能会偏离一点点(加上或减去几行代码),这是一个普遍接受的深度克隆对象的做法吗?是否存在任何陷阱或警告这种方法?

是否未解决同步/并发/线程安全问题?

因为如果这是深度克隆对象的最佳实践方式,我将使用虔诚地

1 个答案:

答案 0 :(得分:2)

这是深度克隆的一种常见做法。缺点是:

  1. 进行序列化/反序列化通常很慢。自定义克隆速度更快。

  2. 它只能克隆可序列化的对象,显然是

  3. 很难知道你序列化了什么。如果你的狗向上指向一些较大的结构(狗包),如果你不注意,克隆一只狗可能会克隆其他一百只狗。 Dog的手动克隆可能只是忽略了包引用,创建了一个具有相同属性的新单个狗对象,可能引用了相同的包狗,但没有克隆包。

  4. 线程安全与手动克隆没有区别。这些属性很可能是由序列化程序从源对象中按顺序读取的,除非您负责线程安全,否则您可以克隆在克隆时部分更改的狗。

    所以我说这可能不建议一直使用它。对于一个非常简单的对象,制作一个简单的手动克隆/复制构造函数很简单,并且性能会更好。对于复杂的对象图,您可能会发现存在克隆您不想要的东西的风险。因此,虽然它很有用,但应谨慎使用。

    顺便说一下,在你的例子中,我使用的是内存流而不是文件流。