浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象(这里的不拷贝是指不会给生成不同的引用地址)
深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
举例:
对象A1中包含对B1的引用,B1中包含对C1的引用,浅拷贝A1得到A2,那么A2中依然包含对B1中的引用,B1中依然包含对C1的引用,也就是说如果你改变C1,B1中属性的值,会引发A1中相应值的变化
深拷贝则会拷贝所有对象的引用,重新指向新的引用。
若不对 Cloneable.clone()方法进行改写,则调用此方法则是浅拷贝
说明:
深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
举例:
对象A1中包含对B1的引用,B1中包含对C1的引用,浅拷贝A1得到A2,那么A2中依然包含对B1中的引用,B1中依然包含对C1的引用,也就是说如果你改变C1,B1中属性的值,会引发A1中相应值的变化
深拷贝则会拷贝所有对象的引用,重新指向新的引用。
若不对 Cloneable.clone()方法进行改写,则调用此方法则是浅拷贝
说明:
之前我以为 A2 = (A1)a1;和 A2 = (A1)a1.clone()是同一概念,实际上是错误的,因为clone其实已经A2和A1的引用地址改变,只是如果A1对象中包含非基本类型时,会仍然引用到之前对象的引用地址
为什么clone()是一个protected作用域呢?
因为作为object中的方法,基于安全,允许子类灵活的重写clone()并定义他的作用域是public还是protected
然而说了这么多,一般不建议使用克隆方法,因为如果一个类重写了Object内定义的clone(),需要同时实现Cloneable接口(虽然这个接口内没有定义clone方法),否则的话,你好在调用clone()时会报 CloneNotSupportedException异常,也就是说,Cloneable接口只是个合法调用clone()的标识(marker-interface)
如果在实际中,若想用到对象的克隆,我们可以借用第三方开源包中的类:
Apache提供了 SerializationUtils.clone(T),T对象需要实现 Serializable 接口,他属于深克隆
同时还可以使用 BeanUtils.cloneBean(T) 来进行浅克隆,但要注意的是,T对象必须有一个不带参数的构造函数,而且它的类还必须为public