如何复制一个对象 | Java Debug 笔记

1,029 阅读2分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接

问题

如何复制一个对象?

假设我有如下代码:

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // 打印出 'foo'

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // 打印出 'foo'

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // 打印出 'bar' 但本应打印 'foo'

因此,如果我想把 dum 复制到 dumtwo 中,但是又想在改变 dum 不影响 dumtwo,单以上代码却无法实现。当我改变 dum 时,dumtwo 也同样发生了改变。

因此我猜想,当我使用 dumtwo = dum 时,Java 中只是复制了引用。

回答

回答 1

创建一个复制构造器:

class DummyBean {
    private String dummy;

    public DummyBean(DummyBean another) {
        this.dummy = another.dummy; // you can access  
    }
}

每个对象都有一个 clone() 方法,可以用来复制对象,但最好不要使用该方法。创建一个类并执行 clone() 方法而导致出错的情况太常见了,如果你经常这么干的话,那最好去读读 《Effective Java》。

回答 2

假设我们有一个对象 obj1,然后包括两个字段 containedObj1containedObj2

  • 浅拷贝

浅拷贝创建同一类的一个新实例,比将所有字段复制到新的实例中,然后将其返回。Object 类提供了一个 clone() 方法,从而方便我们实现浅拷贝。

  • 深拷贝

当一个对象连同他所引用的对象一起被复制时,此时发生的拷贝就叫做深拷贝。下图显示了深拷贝后的 obj1,不仅 obj1 被复制了,而且包括 obj1 所包含的对象也被复制了。我们可以使用 Java 对象序列来实现深拷贝,但该方法也存在一定的缺点(详见实例)。

  • 可能存在的问题

要正确地实现 clone() 很难,推荐使用复制构造函数、静态工厂方法或者保护性拷贝的方式。

如果你有一个对象,而且它有一个公共的 clone() 方法,但你在编译时不知道对象的类型,那么就会出现问题。Java 中有一个 Cloneable 接口,在实际使用过程中,如果我们想要使得一个对象是可复制的,就应该实现该接口。Object.cloneprotected 修饰的,要想让它被我们公开调用,则必须对它进行重写。

另一个出现的问题就是当我们尝试复杂对象的深拷贝时,假设 clone() 方法将所有成员变量也都做了深拷贝。那这样做的话就太冒险了,我们必须对类中的代码实现全局性的控制。

回答 3

org.apache.commons.lang.SerializationUtils 包中,存在着一个 clone() 方法:

SerializationUtils.clone(Object);

使用实例如下:

this.myObjectCloned = SerializationUtils.clone(this.object);

出处

文章翻译自 Stack Overflow:How do I copy an object in Java?