Java对象克隆
使用场景:当需要生成一个和当前对象完全一样的对象时,简单赋值语句不能满足这种需求。
克隆分类:浅克隆、深克隆
浅克隆:对于基本类型属性复制一份给新产生的对象,引用类型的属性仅复制一份引用地址给新产生的对象,即新生成的对象和原对象的非基础类型的数据都指向同一个对象。
深克隆:相对于浅克隆区别在于,对于属性中引用的对象也会被克隆,不在指向原来的地址。
深浅克隆都会在堆中新分配一片区域,区别在于对象属性引用的对象是否还要克隆(递归)
转自 https://www.cnblogs.com/liqiangchn/p/9465186.html
浅克隆代码实现:
1.实现java.lang.Cloneable接口
如果不实现Cloneable 接口而去调用Object的 clone()会抛出CloneNotSupportedException异常。
2.重写clone()方法,并修改protected 为public
深度克隆代码:
方式一 :
1.克隆的类和类中所有非基本的数据类型的属性,都需要实现Cloneable 接口
2.重写clone()方法
方式二:使用对象序列化和反序列化实现深度克隆
对象序列化就是把对象转换为字节流,然后在通过这些值在生成相同状态的对象,但是需要注意如果之前序列化的对象的类,发生改动然后在反序列化之前的对象将会出现异常。可以通过serialVersionUID 属性来解决这个问题。
经过测试发现:
复制引用类型域 效率 > 序列化的方式
第三方工具类相关实现
Bean复制的几种框架中(Apache BeanUtils、PropertyUtils,Spring BeanUtils,Cglib BeanCopier)都是相当于克隆中的浅克隆。
1)spring包和Apache中的 BeanUtils 采用反射实现
Spring: void copyProperties(Object source, Object target,String[] ignoreProperties)
Apache:void copyProperties(Object dest, Object orig)
2)cglib包中的 Beancopier 采用动态字节码实现
cglib: BeanCopier create(Class source, Class target,boolean useConverter)
例如:
BeanCopier copier =BeanCopier.create(stuSource.getClass(), stuTarget.getClass(), false);
copier.copy(stuSource, stuTarget, null);
效率方面:
cglib BeanCopier > Spring BeanUtil > apache BeanUtils