如何在Java中复制对象?
考虑下面的代码:
DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'
DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'
dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'
因此,我想复制dum到dumtwo并且更改dum而不影响dumtwo。但是上面的代码没有做到这一点。当我更改时dum,也会发生相同的更改dumtwo。
我想,当我说时dumtwo = dum,Java仅复制参考。那么,有什么方法可以创建的新副本dum并将其分配给dumtwo?
高分回答:
创建一个副本构造函数:
class DummyBean {
private String dummy;
public DummyBean(DummyBean another){
this.dummy = another.dummy; // you can access
每个对象都有一个克隆方法,可用于复制对象,但不要使用它。创建类和执行不正确的克隆方法太容易了。如果您要这样做,请至少阅读Joshua Bloch在Effective Java中要说的话。
高分回答:
基本: Java中的对象复制。
让我们假设一个对象- obj1,它包含两个对象,containedObj1和containedObj2。 在此处输入图片说明
浅表复制:
浅表复制创建instance相同类的新表,并将所有字段复制到新实例并返回它。对象类提供了一种clone方法,并提供了对浅表复制的支持。
在此处输入图片说明
深度复制:
深度复制是将对象及其引用的对象一起复制时发生的。下图显示了obj1在其上执行深度复制之后的情况。不仅已obj1被复制,而且包含在其中的对象也已被复制。我们可以Java Object Serialization用来制作深层副本。不幸的是,这种方法也存在一些问题(详细示例)。
在此处输入图片说明
可能的问题:
clone难以正确实施。
最好使用防御性复制,复制构造函数(如@egaga回复)或静态工厂方法。
如果您有一个对象,就知道它有一个公共clone()方法,但是在编译时却不知道该对象的类型,那么您就遇到了问题。Java有一个名为的接口Cloneable。在实践中,如果要创建对象,则应实现此接口Cloneable。Object.clone是protected,因此我们必须使用公共方法覆盖它,以便对其进行访问。
当我们尝试对复杂对象进行深度复制时,会出现另一个问题。假设所有成员对象变量的方法也都进行深层复制,那么进行假设的风险太大。您必须控制所有类中的代码。clone()
例如,org.apache.commons.lang.SerializationUtils将具有使用序列化(来源)进行深度克隆的方法。如果我们需要克隆Bean,那么org.apache.commons.beanutils(源)中有几个实用程序方法。
cloneBean 即使bean类本身未实现Cloneable,也会基于可用的属性getter和setter克隆bean。copyProperties 在属性名称相同的所有情况下,都会将属性值从原始Bean复制到目标Bean。