我正在阅读Joshua Bloch的Effective Java。在其中,他谈到不要使用Clonable接口。作为一个新手,我的问题是,什么情况下需要在代码中使用克隆?有人能给我一个具体的例子,以便我能够理解这个概念吗?
clone()
接口提供了创建对象的"浅"副本的机制。也就是说, 默认情况下会为副本分配更多的内存,并将原始对象的每个部分复制到副本中。相比之下,将一个对象实例简单地赋值给一个变量将导致对同一对象的另一个引用。虽然克隆对象本身是真正的副本,但它包含的元素默认情况下是指向原始对象所指向的元素的引用。如果需要真正的“深层”副本,则需要专门设置clone()
方法来创建其成员的克隆。clone()
接口的案例是实现对象的版本历史记录,以允许将其回滚到旧版本。这可以在事务性系统(例如数据库)中使用。*感谢和赞扬newacct纠正克隆描述。
clone()
来克隆对象。 真正的副本意味着新创建的对象的所有属性都应该与您克隆的对象相同。如果您可以使用new实例化类,那么您将获得一个带有所有属性的对象作为它们的初始值。例如,如果您正在设计一个用于执行银行账户交易的系统,那么您将希望复制保存您账户信息的对象,对其进行交易,然后用修改后的对象替换原始对象。在这种情况下,您将希望使用clone()
而不是new。”MyObj first = new MyObj(someOwner, someTag, someInt);
MyObj second = first;
MyObj third = (MyObj) first.clone();
class MyObj implements Cloneable {
private Person owner;
private NameTag tag;
private int size;
public MyObj(Person owner, NameTag tag, int size) {
this.owner = owner;
this.tag = tag;
this.size = size;
}
public Object clone() {
MyObj result;
//call all super clone() methods before doing class specific work
//this ensures that no matter where you are in the inheritance heirarchy,
//a deep copy is made at each level.
try {
result = (MyObj) super.clone();
}
catch (CloneNotSupportedException e) {
throw new RuntimeException
("Super class doesn't implement cloneable");
}
//work specific to the MyObj class
result.owner = owner; //We want the reference to the Person, not a clone
result.tag = tag.clone() //We want a deep copy of the NameTag
result.size = size; //ints are primitive, so this is a copy operation
return result;
}
MyObj
有一个“复制构造函数”(一个接受MyObj
的构造函数)并使用它来创建对象更好吗? - newacct其中一个例子是参数的防御性拷贝(Effective Java第39条:必要时进行防御性拷贝)
class X {
private byte[] a;
X(byte[] a) {
this.a = a.clone();
}
...
clone()
方法,在这种情况下,它将为这些部分执行它们的操作。但自1997年以来,我从未在生产Java中使用过clone()
,也从未使用所谓的“复制构造函数”。从未遇到过真正需要它的要求。 - user207421