三、克隆:无需调用构造器返回新的对象的引用。(最好提供某些其他的途径来代替对象拷贝,或者干脆不提供这样的功能,除非拷贝数组)
分类:浅克隆:引用相同对象。
深克隆:引用相同对象的拷贝。
规定:①x.clone().getClass()通常应该等同于x.getClass() ;(不必须)
②无需调用构造器; //在非final域的情况下,clone可能会返回一个由构造器创建的对象
③Object的clone方法没有实现线程同步。因此,线程安全的类必须编写同步的clone()方法来调用super.clone()。
④链表属于可变引用类型。链表类型需要递归或迭代复制对象。如HashTable中的Entry。
问题一:什么时候可以用浅克隆?什么时候需要用到深克隆?
原理:如果原始对象与浅克隆对象共享的子对象是不可变的,则可以使用浅克隆。如string类型。
问题二:为什么clone()有时会出现浅克隆,有时候出现深克隆?
原理:详细解释:因为在Object类中,clone方法是被声明为protect的。虽然所有类都是Object类型的子类,但是protect规则十分巧妙。子类只能调用受保护方法clone克隆自己,而子类的可变数据成员则不然。
问题三:覆写clone(),为什么一定要实现Cloneable标志性接口?(通过instance of判断)
原理:简单:实现标志接口使得类具有特殊性。编译器在编译的时候已经识别哪些类是具备特殊能力的。
详细:mixin接口,以表明实现类提供了某些可供选择的行为,允许任选的功能可被混合到类型的主要功能中。
例如:在序列化中,在编译时期已经确定该类能否序列化,不需要的运行时在确立,大大加快了运行速度而且也添加了程序的可读性。
解决步骤:
①默认的clone方法是否满足需求?(就算满足也要覆写clone方法)
实例:
package com.itaem;
public class Employee implements Cloneable{
public Employee clone() throws CloneNotSupportedException{
return (Employee) super.clone() ;
}
②默认的clone方法是否能够通过调用可变子对象的clone得到修补?
实例:
package com.itaem;
import java.util.Date;
public class Employee implements Cloneable{
public Employee clone() throws CloneNotSupportedException{
//本类克隆
Employee cloned = (Employee) super.clone() ;
//字段克隆
cloned.hireDay = (Date) hireDate.clone() ;
}
③是否不应该使用clone?(默认,自定义实现)