【问题标题】:Deep copy "Object" type [duplicate]深拷贝“对象”类型[重复]
【发布时间】:2013-06-06 22:21:15
【问题描述】:

我有一个对象类型为“对象”:

class MyObject{
    Object member;

    public Object getObject(){
        return member;
     }

     public void setObject(Object obj){
         member = obj;
     }
}

是否可以深拷贝MyObject

【问题讨论】:

  • 这里不能保证深拷贝,因为 Object 可以是任何东西。例如,如果不是所有的 Object 成员都实现 Serializable,这里的序列化技术就会失败。

标签: java deep-copy


【解决方案1】:

实现Cloneable标记接口,可以通过克隆复制MyObject

class MyObject implements Cloneable {
    public Object clone(){
      try {
        return super.clone();
      } catch (CloneNotSupportedException e) {
           return null; 
      }
   }
}

成员还需要是Cloneable,否则会抛出CloneNotSupportedException。 ...

MyObject obj = new MyObject();
MyObject obj1 = obj.clone();

【讨论】:

  • 那是Cloneable ;)
  • +1 太快太尖锐:)
  • 如果member 不是Cloneable 怎么办?
  • 嗯... clone() 真的很深拷贝吗,我认为除非被覆盖只是逐个字段复制...?
【解决方案2】:

尽管它是一个 bean,因此不是不可变的,但我有一个替代方案:freeze/thaw pattern

如果您为您的对象实现它(这将需要您使用构建器类),那么您可以这样做:

final MyObject copy = orig.thaw().freeze();

我发现它比 Cloneable 甚至构建器(这是一个可逆构建器)更方便,并且经常使用这种模式。

作为奖励,您可以使您的对象不是 bean,因此是不可变的。我个人非常不喜欢豆子,这就是我想出这个的原因......

而且这种模式也是递归的。假设您有 OutIn 类,其中 InOut 的成员。假设In 服从冻结/解冻。您的Out 代码将变为:

public final class Out
    implements Frozen<Builder>
{
    private final In in;

    private Out(final Builder builder)
    {
        in = builder.in.freeze();
    }

    public static newBuilder()
    {
        return new Builder();
    }

    public In getIn()
    {
        return in;
    }

    @Override
    public Builder thaw()
    {
        return new Builder(this);
    }

    public static final class Builder
        implements Thawed<Out>
    {
        private In.Builder in;

        private Builder()
        {
        }

        private Builder(final Out out)
        {
            in = out.in.thaw();
        }

        public Builder setIn(final In in)
        {
            this.in = in.thaw();
        }

        @Override
        public Out freeze()
        {
            return new Out(this);
        }
    }
}

最终结果是调用copy = orig.thaw().frezze() 会返回一个相同的副本,其中包含in 实例。

【讨论】:

    【解决方案3】:

    在目前的实现中这是不可能的,因为member 可以是任何东西,你不能复制你不知道的东西。

    【讨论】:

    • +1,这是正确答案。
    • +1 没有办法保证一个对象是可复制的,无论是深的还是浅的,直到运行时它唯一保证的接口是对象。
    • 我认为可以使用reflection
    • @RongNK 您可以使用反射复制一些对象(性能相当糟糕),但不是全部。想到数据库/网络连接和打开的文件。
    • @JoachimIsaksson 好的 :-)
    猜你喜欢
    • 2015-09-14
    • 2011-02-09
    • 2015-04-28
    • 1970-01-01
    • 2017-10-14
    • 1970-01-01
    • 2012-06-19
    • 2019-11-17
    • 1970-01-01
    相关资源
    最近更新 更多