中年从原型模式到浅拷贝和深拷贝( 三 )


深拷贝与浅拷贝 。 Object 类的 clone方法只会拷贝对象中的基本的数据类型 , 对于数组、容器对象、引用对象等都不会拷贝 , 这就是浅拷贝 。 如果要实现深拷贝 , 必须将原型模式中的数组、容器对象、引用对象等另行拷贝 。
浅拷贝和深拷贝
首先需要明白 , 浅拷贝和深拷贝都是针对一个已有对象的操作 。
在 Java 中 , 除了基本数据类型(元类型)之外 , 还存在 类的实例对象 这个引用数据类型 。 而一般使用 『 = 』号做赋值操作的时候 。 对于基本数据类型 , 实际上是拷贝的它的值 , 但是对于对象而言 , 其实赋值的只是这个对象的引用 , 将原对象的引用传递过去 , 他们实际上还是指向的同一个对象 。
而浅拷贝和深拷贝就是在这个基础之上做的区分 , 如果在拷贝这个对象的时候 , 只对基本数据类型进行了拷贝 , 而对引用数据类型只是进行了引用的传递 , 而没有真实的创建一个新的对象 , 则认为是浅拷贝 。 反之 , 在对引用数据类型进行拷贝的时候 , 创建了一个新的对象 , 并且复制其内的成员变量 , 则认为是深拷贝 。
“ 所谓的浅拷贝和深拷贝 , 只是在拷贝对象的时候 , 对 类的实例对象 这种引用数据类型的不同操作而已 浅拷贝 对于数据类型是基本数据类型的成员变量 , 浅拷贝会直接进行值传递 , 也就是将该属性值复制一份给新的对象 。
对于数据类型是引用数据类型的成员变量 , 比如说成员变量是某个数组、某个类的对象等 , 那么浅拷贝会进行引用传递 , 也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象 。 因为实际上两个对象的该成员变量都指向同一个实例 。 在这种情况下 , 在一个对象中修改该成员变量会影响到另一个对象的该成员变量值
前面我们克隆羊就是浅拷贝 , 如果我们在 Sheep 中加一个对象类型的属性 , public Sheep child可以看到 s 和 s1 的 friend 是同一个 。
Sheep s = new Sheep() s.setName("sss")
s.friend = new Sheep() s.friend.setName("喜洋洋")
Sheep s1 = s.clone() System.out.println(s == s1) System.out.println(s.hashCode()+"---"+s.clone().hashCode())
System.out.println(s.friend == s1.friend) System.out.println(s.friend.hashCode() + "---" +s1.friend.hashCode()) false621009875---1265094477true2125039532---2125039532 深拷贝
现在我们知道 clone() 方法 , 只能对当前对象进行浅拷贝 , 引用类型依然是在传递引用 。 那如何进行一个深拷贝呢?
常见的深拷贝实现方式有两种:
重写 clone 方法来实现深拷贝
通过对象序列化实现深拷贝
浅拷贝和深拷贝只是相对的 , 如果一个对象内部只有基本数据类型 , 那用 clone() 方法获取到的就是这个对象的深拷贝 , 而如果其内部还有引用数据类型 , 那用 clone() 方法就是一次浅拷贝的操作 。
单例 拷贝 调用 子类 clone声明:转载此文是出于传递更多信息之目的 。 若有来源标注错误或侵犯了您的合法权益 , 请作者持权属证明与本网联系 , 我们将及时更正、删除 , 谢谢 。邮箱地址:newmedia@xxcb.cn


推荐阅读