本文正在参加「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,然后包括两个字段 containedObj1 和 containedObj2。
- 浅拷贝
浅拷贝创建同一类的一个新实例,比将所有字段复制到新的实例中,然后将其返回。Object 类提供了一个 clone() 方法,从而方便我们实现浅拷贝。
- 深拷贝
当一个对象连同他所引用的对象一起被复制时,此时发生的拷贝就叫做深拷贝。下图显示了深拷贝后的 obj1,不仅 obj1 被复制了,而且包括 obj1 所包含的对象也被复制了。我们可以使用 Java 对象序列来实现深拷贝,但该方法也存在一定的缺点(详见实例)。
- 可能存在的问题
要正确地实现 clone() 很难,推荐使用复制构造函数、静态工厂方法或者保护性拷贝的方式。
如果你有一个对象,而且它有一个公共的 clone() 方法,但你在编译时不知道对象的类型,那么就会出现问题。Java 中有一个 Cloneable 接口,在实际使用过程中,如果我们想要使得一个对象是可复制的,就应该实现该接口。Object.clone 是 protected 修饰的,要想让它被我们公开调用,则必须对它进行重写。
另一个出现的问题就是当我们尝试复杂对象的深拷贝时,假设 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?