Effective Java:Ch3_Methods:Item11_谨慎重写clone()
Cloneable接口的目的是作为对象的一个mixin接口,表明对象允许克隆;但这个目的没有达到。
其主要缺点是,Cloneable缺少一个clone()方法,而Object.clone()是受保护的。
通常,实现接口是为了表明类可以为它的客户做些什么;而Cloneable却是改变了超类中受保护方法的行为。
Object.clone()定义的约定:
[java]
/**
创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。一般来说,对于任何对象 x,如果表达式:
x.clone() != x
是正确的,则表达式:
x.clone().getClass() == x.getClass()将为 true,
但这些不是绝对条件。一般情况下是:
x.clone().equals(x)将为 true,但这不是绝对条件。
--按照惯例,返回的对象应该通过调用 super.clone 获得。
如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。
--按照惯例,此方法返回的对象应该独立于该对象(正被克隆的对象)。
要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。
这通常意味着要复制包含正在被克隆对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。
如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。
Object 类的 clone 方法执行特定的克隆操作。
首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。
注意:所有的数组都被视为实现接口 Cloneable。
否则,此方易做图创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;
这些字段的内容没有被自我克隆。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。
Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。
*/
protected native Object clone() throws CloneNotSupportedException;
/**
创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。一般来说,对于任何对象 x,如果表达式:
x.clone() != x
是正确的,则表达式:
x.clone().getClass() == x.getClass()将为 true,
但这些不是绝对条件。一般情况下是:
x.clone().equals(x)将为 true,但这不是绝对条件。
--按照惯例,返回的对象应该通过调用 super.clone 获得。
如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。
--按照惯例,此方法返回的对象应该独立于该对象(正被克隆的对象)。
要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。
这通常意味着要复制包含正在被克隆对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。
如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。
Object 类的 clone 方法执行特定的克隆操作。
首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。
注意:所有的数组都被视为实现接口 Cloneable。
否则,此方易做图创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;
这些字段的内容没有被自我克隆。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。
Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。
*/
protected native Object clone() throws CloneNotSupportedException;
所有实现了Cloneable接口的类,都应该提供一个public的clone()方法;
在这个clone()方法中,首先调用super.clone(),然后修正任何需要修正的域。
例如Hashtable.clone()
[java]
/**
* Creates a shallow copy of this hashtable. All the structure of the
* hashtable itself is copied, but the keys and values are not cloned.
* This is a relatively expensive operation.
*
* @return a clone of the hashtable
*/
public synchronized Object clone() {
try {
Hashtable<K,V> t = (Hashtable<K,V>) super.clone(); // --super.clone()
t.table = new Entry[table.length];
for (int i = table.length ; i-- > 0 ; ) {
t.table[i] = (table[i] != null)
? (Entry<K,V>) table[i].clone() : null; // --递归调用实例变量.clone()
}
t.keySet = null;
t.entrySet = null;
t.values = null;
t.modCount = 0;
return t;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* Creates a shallow copy of this hashtable. All the structure of the
* hashtable itself is copied, but the keys and values are not cloned.
* This is a relatively expensive operation.
*
* @return a clone of the hashtable
*/
public synchronized Object clone() {
try {
Hashtable<K,V> t = (Hashtable<K,V>) super.clone(); // --super.clone()
t.table = new Entry[table.length];
for (int i = table.length ; i-- > 0 ; ) {
t.table[i] = (table[i] != null)
? (Entry<K,V>) table[i].clone() : null; // --递归调用实例变量.clone()
}
t.keySet = null;
t.entrySet = null;
t.values = null;
t.modCount = 0;
return t;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}注意,递归调用实例变量.clone()时,如果该变量为final,则不行!clone架构与饮用可变对象的final域的正常用法是不兼容的!
另一个实现对象拷贝的好办法是提供一个拷贝构造器(copy constructor)或者拷贝工厂(copy factory)。
例如:
[java]
public Yum(Yum yum);
public static Yum newInstance(Yum yum);
public Yum(Yum yum);
public static Yum newInstance(Yum yum);
这种方法比clone有更多优势:
不依赖于某一种有风险的、语言之外的对象创建机制
不要求遵守尚未制定好文档的规范
不会与final域的正常使用发生冲突
不会抛出不必要的受检异常
不需要进行类型转换
另外,拷贝构造器和拷贝工厂可以带参数,参数类型一般是该类实现的接口,以便用户选择拷贝的实现类型。
例如,有一个HashSet s,希望把它拷贝成一个TreeSet,可以调用:new TreeSet(s)
[java]
/**
* Constructs a new tree set containing the elements in the specified
* collection, sorted according to the <i>natural ordering</i> of its
* elements.&nbs
补充:软件开发 , Java ,