问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

深拷贝和浅拷贝怎样理解(通俗具体点儿)

发布网友 发布时间:2022-04-21 07:45

我来回答

5个回答

热心网友 时间:2022-06-18 19:01

浅拷贝就是指对象复制的时候只复制一层;深拷贝是指复制对象的所有层级。

深拷贝和浅拷贝,主要是对象发生复制的时候,根据复制的层级不同来区分的。很多人在这里经常变量赋值发生混淆。对于JavaScript数组等复杂的数据类型来说,将其赋值给其它变量,其实只是复制了对象的地址给它,两个变量指向的是同一个对象,因此普通的赋值既不是深拷贝也不是浅拷贝。

深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝:

在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去。

而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。

热心网友 时间:2022-06-18 19:02

JAVA技术之深拷贝与浅拷贝   在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。在Java语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单,也是最高效的手段。  Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象返回的是一个新对象,而不是一个引用。二是拷贝对象与用new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。  怎样应用clone()方法?  一个很典型的调用clone()代码如下:  01class CloneClass implements Cloneable{  02 public int aInt;  03 public Object clone(){  04 CloneClass o = null;  05 try{  06 o = (CloneClass)super.clone();  07 }catch(CloneNotSupportedException e){  08 e.printStackTrace();  09 }  10 return o;  11 }  12}  有三个值得注意的地方,一是希望能实现clone功能的CloneClass类实现了Cloneable接口,这个接口属于java.lang包,java.lang包已经被缺省的导入类中,所以不需要写成java.lang.Cloneable。另一个值得请注意的是重载了clone()方法。最后在clone()方法中调用了super.clone(),这也意味着无论clone类的继承结构是什么样的,super.clone()直接或间接调用了java.lang.Object类的clone()方法。下面再详细的解释一下这几点。  应该说第三点是最重要的,仔细观察一下Object类的clone()一个native方法,native方法的效率一般来说都是远高于java中的非native方法。这也解释了为什么要用Object中clone()方法而不是先new一个类,然后把原始对象中的信息赋到新对象中,虽然这也实现了clone功能。对于第二点,也要观察Object类中的clone()还是一个protected属性的方法。这也意味着如果要应用clone()方法,必须继承Object类,在Java中所有的类是缺省继承Object类的,也就不用关心这点了。然后重载clone()方法。还有一点要考虑的是为了让其它类能调用这个clone类的clone()方法,重载之后要把clone()方法的属性设置为public。  那么clone类为什么还要实现Cloneable接口呢?稍微注意一下,Cloneable接口是不包含任何方法的!其实这个接口仅仅是一个标志,而且这个标志也仅仅是针对Object类中clone()方法的,如果clone类没有实现Cloneable接口,并调用了Object的clone()方法(也就是调用了super.Clone()方法),那么Object的clone()方法就会抛出CloneNotSupportedException异常。  注意:1.所有的数组都被视为实现接口 Cloneable。  2.Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。  以上是clone的最基本的步骤,想要完成一个成功的clone,还要了解什么是"影子clone"和"深度clone"。  什么是影子clone?  下面的例子包含三个类UnCloneA,CloneB,CloneMain。CloneB类包含了一个UnCloneA的实例和一个int类型变量,并且重载clone()方法。CloneMain类初始化UnCloneA类的一个实例b1,然后调用clone()方法生成了一个b1的拷贝b2。最后考察一下b1和b2的输出:  01package clone;  02class UnCloneA {  03 private int i;  04 public UnCloneA(int ii) { i = ii; }  05 public void doubleValue() { i *= 2; }  06 public String toString() {  07 return Integer.toString(i);  08 }  09}  10class CloneB implements Cloneable{  11 public int aInt;  12 public UnCloneA unCA = new UnCloneA(111);  13 public Object clone(){  14 CloneB o = null;  15 try{  16 o = (CloneB)super.clone();  17 }catch(CloneNotSupportedException e){  18 e.printStackTrace();  19 }  20 return o;  21 }  22}  23public class CloneMain {  24 public static void main(String[] a){  25 CloneB b1 = new CloneB();  26 b1.aInt = 11;  27 System.out.println("before clone,b1.aInt = "+ b1.aInt);  28 System.out.println("before clone,b1.unCA = "+ b1.unCA);  29  30 CloneB b2 = (CloneB)b1.clone();  31 b2.aInt = 22;  32 b2.unCA.doubleValue();  33 System.out.println("=================================");  34 System.out.println("after clone,b1.aInt = "+ b1.aInt);  35 System.out.println("after clone,b1.unCA = "+ b1.unCA);  36 System.out.println("=================================");  37 System.out.println("after clone,b2.aInt = "+ b2.aInt);  38 System.out.println("after clone,b2.unCA = "+ b2.unCA);  39 }  40}  41  42  43  44  输出的结果说明int类型的变量aInt和UnCloneA的实例对象unCA的clone结果不一致,int类型是真正的被clone了,因为改变了b2中的aInt变量,对b1的aInt没有产生影响,也就是说,b2.aInt与b1.aInt已经占据了不同的内存空间,b2.aInt是b1.aInt的一个真正拷贝。相反,对b2.unCA的改变同时改变了b1.unCA,很明显,b2.unCA和b1.unCA是仅仅指向同一个对象的不同引用!从中可以看出,调用Object类中clone()方法产生的效果是:先在内存中开辟一块和原始对象一样的空间,然后原样拷贝原始对象中的内容。对基本数据类型,这样的操作是没有问题的,但对非基本类型变量,我们知道它们保存的仅仅是对象的引用,这也导致clone后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。  大多时候,这种clone的结果往往不是我们所希望的结果,这种clone也被称为"影子clone"。要想让b2.unCA指向与b2.unCA不同的对象,而且b2.unCA中还要包含b1.unCA中的信息作为初始信息,就要实现深度clone。  怎么进行深度clone?  把上面的例子改成深度clone很简单,需要两个改变:一是让UnCloneA类也实现和CloneB类一样的clone功能(实现Cloneable接口,重载clone()方法)。二是在CloneB的clone()方法中加入一句o.unCA = (UnCloneA)unCA.clone();  程序如下:  01package clone.ext;  02class UnCloneA implements Cloneable{  03 private int i;  04 public UnCloneA(int ii) { i = ii; }  05 public void doubleValue() { i *= 2; }  06 public String toString() {  07 return Integer.toString(i);  08 }  09 public Object clone(){  10 UnCloneA o = null;  11 try{  12 o = (UnCloneA)super.clone();  13 }catch(CloneNotSupportedException e){  14 e.printStackTrace();  15 }  16 return o;  17 }  18}  19class CloneB implements Cloneable{  20 public int aInt;  21 public UnCloneA unCA = new UnCloneA(111);  22 public Object clone(){  23 CloneB o = null;  24 try{  25 o = (CloneB)super.clone();  26 }catch(CloneNotSupportedException e){  27 e.printStackTrace();  28 }  29 o.unCA = (UnCloneA)unCA.clone();  30 return o;  31 }  32}  33public class CloneMain {  34 public static void main(String[] a){  35 CloneB b1 = new CloneB();  36 b1.aInt = 11;  37 System.out.println("before clone,b1.aInt = "+ b1.aInt);  38 System.out.println("before clone,b1.unCA = "+ b1.unCA);  39  40 CloneB b2 = (CloneB)b1.clone();  41 b2.aInt = 22;  42 b2.unCA.doubleValue();  43 System.out.println("=================================");  44 System.out.println("after clone,b1.aInt = "+ b1.aInt);  45 System.out.println("after clone,b1.unCA = "+ b1.unCA);  46 System.out.println("=================================");  47 System.out.println("after clone,b2.aInt = "+ b2.aInt);  48 System.out.println("after clone,b2.unCA = "+ b2.unCA);  49 }  50}  51  可以看出,现在b2.unCA的改变对b1.unCA没有产生影响。此时b1.unCA与b2.unCA指向了两个不同的UnCloneA实例,而且在CloneB b2 = (CloneB)b1.clone();调用的那一刻b1和b2拥有相同的值,在这里,b1.i = b2.i = 11。  要知道不是所有的类都能实现深度clone的。例如,如果把上面的CloneB类中的UnCloneA类型变量改成StringBuffer类型,看一下JDK API中关于StringBuffer的说明,StringBuffer没有重载clone()方法,更为严重的是StringBuffer还是一个final类,这也是说我们也不能用继承的办法间接实现StringBuffer的clone。如果一个类中包含有StringBuffer类型对象或和StringBuffer相似类的对象,我们有两种选择:要么只能实现影子clone,要么就在类的clone()方法中加一句(假设是SringBuffer对象,而且变量名仍是unCA): o.unCA = new StringBuffer(unCA.toString()); //原来的是:o.unCA = (UnCloneA)unCA.clone();  还要知道的是除了基本数据类型能自动实现深度clone以外,String对象是一个例外,它clone后的表现好象也实现了深度clone,虽然这只是一个假象,但却大大方便了我们的编程。]

热心网友 时间:2022-06-18 19:02

浅拷贝就是成员数据之间的一一赋值:把值赋给一一赋给要拷贝的值。但是可能会有这样的情况:对象还包含资源,这里的资源可以值堆资源,或者一个文件。。当值拷贝的时候,两个对象就有用共同的资源,同时对资源可以访问,这样就会出问题。深拷贝就是用来解决这样的问题的,它把资源也赋值一次,使对象拥有不同的资源,但资源的内容是一样的。对于堆资源来说,就是在开辟一片堆内存,把原来的内容拷贝。
如果你拷贝的对象中引用了某个外部的内容(比如分配在堆上的数据),那么在拷贝这个对象的时候,让新旧两个对象指向同一个外部的内容,就是浅拷贝;如果在拷贝这个对象的时候为新对象制作了外部对象的独立拷贝,就是深拷贝
引用和指针的语义是相似的,引用是不可改变的指针,指针是可以改变的引用。其实都是实现了引用语义。

热心网友 时间:2022-06-18 19:03

浅复制: 实现浅复制需要使用Object类的MemberwiseClone方法用于创建一个浅表副本 深复制: 须实现 ICloneable接口中的Clone方法,且需要需要克隆的对象加上[Serializable]特性文章转载自网管网:http://www.bitscn.com/pdb/dotnet/201003/181980.html]

热心网友 时间:2022-06-18 19:03

http://www.bitscn.com/pdb/dotnet/201003/181980.html]
什么是浅拷贝(shallow copy)和深拷贝(deep copy)

深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。COW语义是“深拷贝”与“推迟计算”的组合,仍然是深拷贝,而非浅拷贝,因为拷贝之后的两个对象的数据在逻辑上是不相关的,只是内容相同。举个简单的例子:...

python深拷贝和浅拷贝的区别

所谓“深拷贝”,是指创建一个新的对象,然后递归的拷贝原对象所包含的子对象。深拷贝出来的对象与原对象没有任何关联。深拷贝只有一种方式:copy模块中的deepcopy函数。总结:copy浅拷贝,没有拷贝子对象,所以原始数据改变,子对象会改变 深拷贝,包含对象里面的自对象的拷贝,所以原始对象的改变不会造...

python深拷贝和浅拷贝的区别

2、copy浅拷贝,没有拷贝子对象,所以原始数据改变,子对象会改变。3、深拷贝,包含对象里面的自对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变。Python的语句不同于C++等编程语言。Python的语句末尾不需要加分号表示语句结束,直接换行即可。另外很重要的一点,就是使用缩进表示语句块之间...

浅拷贝与深拷贝的区别

浅拷贝是指创建一个新对象,这个对象有着原始对象的一些引用类型的属性值的初始引用,也就是说,新对象和原始对象共享某些数据。修改浅拷贝对象的这些引用属性时,会影响到原始对象中的相应数据。但对于对象内部的非引用类型属性,如数字、字符串等,浅拷贝会创建这些属性的独立副本,修改浅拷贝对象的这些属...

什么是深拷贝和浅拷贝

浅拷贝就是指对象复制的时候只复制一层;深拷贝是指复制对象的所有层级。深拷贝和浅拷贝,主要是对象发生复制的时候,根据复制的层级不同来区分的。很多人在这里经常变量赋值发生混淆。对于JavaScript数组等复杂的数据类型来说,将其赋值给其它变量,其实只是复制了对象的地址给它,两个变量指向的是同一个...

深浅拷贝是什么,通俗一点

浅拷贝是指将对象内的数据完全一致的复制 深拷贝不是这样,它可以将内部的数据按照需要用特殊的方法拷贝,比如说对象内部有一个动态数组,浅拷贝只拷贝指针,而深拷贝可以重新申请空间并将数据复制过来

python的深拷贝和浅拷贝

浅拷贝只会复制可变对象的一层内容,而不会递归复制可变对象包含的子对象。如果需要递归复制子对象,必须使用深拷贝。当一个对象包含循环引用时,尝试进行深复制可能会导致无限递归,从而导致程序崩溃。因此,在使用深拷贝时,必须小心处理包含循环引用的对象。在使用深拷贝时,如果对象的层次结构比较复杂,...

浅复制和深复制的区别

大体上来说,深拷贝与浅拷贝的区别主要还是在于指针(或与指针)方面,浅拷贝只是简单的把源对象(这个是指广义的对象,不仅仅单指类的实例)的指针赋值给目标对象,对目标指针的操作就是对源对象的操作,所以在很多情况下,目标对象析构(或跳出其可见域)之后,源对象相关部分也就一同析构了。而深...

深拷贝、浅拷贝的理解与使用场景

通俗解释:深拷贝是内容拷贝,浅拷贝是地址拷贝 区别点:深拷贝会创建一个新的内存空间,拷贝的值是一样的,但是内存地址不一样。浅拷贝只是拷贝指向原来对象的地址,使原对象的引用计数+1 像NSString、NSNumber这些不能包含其他对象的叫做非容器类对象 像NSArray、NSDictionary这些可以包含其他对象的叫...

深拷贝和浅拷贝的区别

1、浅拷贝 a、Object.assign()Object.assign()方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。Object.assign()拷贝的是对象的属性的引用,而不是对象本身。2、深拷贝 a、JSON转换 let newObj = JSON.parse(JSON.stringify(obj))。缺点:1) 如果对象有函数,函数无法被...

什么是浅拷贝和深拷贝 深拷贝和浅拷贝如何实现 深拷贝和浅拷贝的方法 浅拷贝和深拷贝什么时候用 深拷贝和浅拷贝的题 js的深拷贝和浅拷贝的区别 怎样拷贝文件 浅拷贝 浅拷贝方法
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
张凤山的策划导演 石家庄商汇民生怎么样啊?和民生人寿是一个系统吗? 法院判决协助执行过户该怎么执行 矛之酒馆0.17高速下载 八字极弱的命格很惨吗,八字极弱的人运势如何 苹果手机怎么下载农鲜达 如何在Excel表格中选择值excel学习网百度知道 支付宝古代学校在夏季放假主要是为了-蚂蚁庄园2023年7月8日今日... 支付宝蚂蚁庄园7月8日答案是什么介绍_支付宝蚂蚁庄园7月8日答案是什么... 广东最好海鲜排名 什么是深拷贝和浅拷贝 浅拷贝与深拷贝的区别 阳光融和医院是阳光保险的吗? 阳光融和医院做的好么? 阳光融和医院跟阳光保险有关系吗? 山东阳光融和医院有限责任公司怎么样? 阳光保险的阳光融和医院获得国际JCI认证了吗? 阳光融和医院是阳光保险建的吗? 听说阳光融和医院是阳光保险近年成立的? 听说阳光融和医院是阳光保险创办的? 听说阳光融和医院是阳光保险做的? 阳光保险创办阳光融和医院了吗? 听说阳光融和医院是阳光保险创办的?是这样的吗 潍坊阳光融合医院招聘吗 是阳光保险成立的阳光融和医院么? 阳光保险的阳光融和医院很好吗?谢谢了。 山东阳光融和医院有限责任公司电话是多少? 阳光融和医院是阳光保险的么? 阳光保险的阳光融和医院是三甲的吗? 阳光保险的阳光融和医院医疗水平怎么样? 求助深拷贝和浅拷贝的问题 转:C#之深拷贝和浅拷贝的区别 什么是浅拷贝(shallow copy)和深拷贝(deep copy) java深拷贝和浅拷贝的区别 C#浅拷贝与深拷贝区别 net中浅拷贝和深拷贝有什么区别,分别如何实现 js深拷贝和浅拷贝的区别 JAVA 中浅拷贝与深拷贝有什么区别? 深拷贝和浅拷贝的区别 新房装修卫生间用蹲坑好还是马桶好 卫生间装马桶好还是蹲便好,看完这些之后再也不用纠结 卫生间是装马桶还是装蹲便器好 卫生间到底装马桶好还是蹲厕好? 卫生间在装修的时候,安装马桶比较好还是蹲坑比较好? 经验,卫生间到底装马桶好还是蹲坑好 卫生间装蹲便器好还是马桶好? 蹲坑和马桶,你家卫生间装修选择哪个 卫生间装修选蹲便器好还是马桶好 卫生间到底装蹲坑还是马桶好,家用马桶和蹲坑哪个好 新房装修卫生间装马桶好还是蹲坑好