2

我正在阅读 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
        }
    }

假设我可能有点偏离(加上或减去几行代码),这是深度克隆对象的普遍接受的做法吗?这种方法有什么陷阱或警告吗?

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

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

4

1 回答 1

2

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

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

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

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

线程安全与手动克隆没有什么不同。序列化程序很可能会从源对象顺序读取属性,除非您注意线程安全,否则您可能会克隆在克隆时部分更改的狗。

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

顺便说一句,在您的示例中,我将使用内存流而不是文件流。

于 2011-09-24T22:12:17.693 回答