问题
考虑以下代码:
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`?
#1 热门回答(520 赞)
创建一个复制构造函数:
class DummyBean {
private String dummy;
public DummyBean(DummyBean another) {
this.dummy = another.dummy; // you can access
}
}
每个对象都有一个克隆方法,可用于复制对象,但不要使用它。创建一个类并执行不正确的克隆方法太容易了。如果你打算这样做,请至少阅读Joshua Bloch在Effective Java中所说的内容。
#2 热门回答(349 赞)
**Basic:**Object以Java格式复制。
让我们假设一个对象 - 'obj1`,它包含两个对象,包含Obj1和包含的Obj2。
浅拷贝:
浅复制创建一个相同类的新实例
并将所有字段复制到新实例并返回它.对象类提供了clone
方法并为浅复制提供支持。
深拷贝:
将对象与其引用的对象一起复制时,会发生深层复制。在下面的图像显示了对它执行深度复制后的obj1
。不仅复制了'obj1,而且还复制了其中包含的对象。我们可以使用
Java Object Serialization`来进行深层复制。不幸的是,这种方法也存在一些问题(detailed examples)。
可能的问题:
clone
很难正确实现。
最好使用Defensive copying,copy constructors(作为@egaga回复)或static factory methods。
- 如果你有一个对象,你知道有一个公共clone()方法,但是你不知道编译时对象的类型,那么你就有问题了。 Java有一个名为Cloneable的接口。实际上,如果我们想要创建一个Cloneable对象,我们应该实现这个接口。 Object.clone受到保护,因此我们必须使用公共方法覆盖它以使其可访问。
- 当我们尝试深度复制复杂对象时,会出现另一个问题。假设所有成员对象变量的clone()方法也进行深度复制,这对假设来说风险太大。你必须控制所有类中的代码。
例如,218181767将有使用序列化的深度克隆方法(Source)。如果我们需要克隆Bean,那么在org.apache.commons.beanutils(Source)中有几种实用方法。
- cloneBean将基于可用属性getter和setter克隆bean,即使bean类本身没有实现Cloneable。
- 对于属性名称相同的所有情况,copyProperties会将属性值从原始bean复制到目标bean。
#3 热门回答(90 赞)
请按以下步骤操作:
public class Deletable implements Cloneable{
private String str;
public Deletable(){
}
public void setStr(String str){
this.str = str;
}
public void display(){
System.out.println("The String is "+str);
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
无论你想要获得另一个对象,只需执行克隆即可。例如:
Deletable del = new Deletable();
Deletable delTemp = (Deletable ) del.clone(); // this line will return you an independent
// object, the changes made to this object will
// not be reflected to other object