1.可以通过实现Cloneable接口重载对象的clone方法,若不实现Cloneable接口而重载clone方法,将会抛出CloneNotSupportedException
异常。(这是比较反常的接口使用,因为Cloneable中没有任何方法,它所修改的父类上受保护方法的行为)
2.clone是唯一个创建对象但是却不需要调用构造方法的方法。
3.clone方法通用规范:创建并返回此对象的副本
- 对于任何对象x,
x.clone()!=x
x.clone().getClass()==x.getClass()
下面解析一下以上规则,x.clone()!=x
,使用的是!=
表示两个对象所引用的堆的对象的地址是不同的,因此不能用简单的Type x=y;
进行复制,第二条:x.clone().getClass==x.getClass()
用的是getClass
而不是instanceof
,说明是严格判断,对于派生类什么的是不行的。
想要实现以上规则,我们需要:
- 对于每个
clone
方法中,给每个对象赋值的时候,需要调用对象的clone
- 对于派生类,需要首先调用
super.clone()
4.重写方法的返回类型可以是重写方法的返回类型的子类。
5.为了使一个类可以被克隆,可能需要从一些属性中移除final修饰符。
6.对于数组,链表,哈希表等容器,最好循环遍历赋值,而不是直接调用容器.clone
7.clone
方法不能再构建过程中调用一个可以重写的方法。如果调用一个可重写的方法,子类很可能在克隆中的进行修复步骤之前执行该方法,这样可能会使得克隆和原始对象的损坏。
8.具有易用性的公共clone
方法最好不要抛出CloneNotSupportedException
9.父类不应该实现Cloneable接口,而是应该交由给子类自己选择是否支持clone
方法。
10.最好的clone方法:
通过类似C++的拷贝构造函数:
public Yum(Yum yum){...};
通过静态工厂
public static Yun newInstance(Yum yum){...};
总之,最好不要实现Cloneable接口,通常,复制功能最好由构造方法或者工厂提公,这个规则有个例外:数组最好使用clone方法复制。