一变二
场景
对象复制的实现目标是
- 生成新对象 x.clone() != x
- 对象类别一致 x.clone().getClass() == x.getClass()
- 对象相等 x.clone().equals(x)
实现
clone是Object类的基本方法之一。
从java.lang.Object类中可以发现并非由Java代码实现,clone并没有调用类构造函数而是进行二进制流拷贝
1 | protected native Object clone() throws CloneNotSupportedException; |
使用类必须实现java.lang.Cloneable接口,Cloneable是一个不包含方法的标识性接口
1 | public interface Cloneable { |
Java原生的java.util.Calendar就是很好的范例
1 | public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> { |
clone方法的实现原则是调用父类clone方法,在继承链条上最终会调用到Object中的实现。Object提供的clone是浅拷贝
机制,因此涉及可变成员的情况下,默认的clone结果是新旧对象持有相同的可变成员引用,新旧对象并没有完全独立。
为了摆脱可变对象的共享,实现深拷贝
,子类要重新实现clone方法。首先用super.clone获取基础,然后强制转换成子类,再把子类的可变属性进行重新赋值。
从实现可以看出常量和long这种基本类型无需特殊逻辑,而数组和可变类TimeZone需要重新赋值,对于数组而言,直接构造新数组,对于可变类,直接交给该类的clone方法。
1 |
|
优缺点
clone要完全利用clone机制实现深拷贝,需要继承链范围内所有成员都实现Cloneable接口并重写clone方法,代价很大。
替代方法:
- 利用序列化: 如果实现了序列化接口,可利用commons-lang SerializationUtils类
- 利用反射:如果没实现序列化接口,只能利用第三方类库通过反射获取信息进行构建
库
- Kryo
- Spring BeanUtil
一分也是爱~
版权声明
This site by Linest is licensed under a Creative Commons BY-NC-ND 4.0 International License.
由Linest创作并维护的博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。