一.引用拷贝与对象拷贝

class Person implements Cloneable{private String name;private int age;。。。省略get和set方法
protected Object clone() throws CloneNotSupportedException {return super.clone();}
}

1.引用拷贝

        Person person=new Person("jerry",23);Person p=person;System.out.println(person);System.out.println(p);
Example.jerry.pratice.Person@4554617c
Example.jerry.pratice.Person@4554617c

person和p地址相同,二者引用同一个对象new Person("jerry",23)。并没有创建出一个新的对象。此种为引用拷贝。

引用拷贝:创建一个指向对象的引用变量的拷贝。

2.对象拷贝

【注】实现对象拷贝的类必须实现Cloneable接口,并覆写clone方法。

Person person=new Person("jerry",23);Person p1=(Person) person.clone();System.out.println(person);System.out.println(p1);
Example.jerry.pratice.Person@4554617c
Example.jerry.pratice.Person@74a14482

peson和p1地址不同,即创建了新的对象,而非把仅仅把地址赋给变量。此种为对象拷贝。

二.深拷贝和浅拷贝

【注】深拷贝和浅拷贝都是对象拷贝

浅拷贝

Def:按位拷贝,会创建一个新对象。这个新对象有原始对象属性值的一份拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址。即如果其中一个对象改变了这个地址,就会影响到另一个对象。【浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象】

class Info implements Cloneable{private Person person;private String city;private int    id;。。。。省略get和set方法public Object clone() throws CloneNotSupportedException {Object object = super.clone();return object;}
}

在原来的基础上加上Info类,引用原来的Person类

Person person=new Person("jerry",23);Info info=new Info();info.setCity("北京");info.setId(11111);info.setPerson(person);Info info1=(Info)info.clone();System.out.println("拷贝后,,,");System.out.println(info);System.out.println(info1);System.out.println(info1.getId());System.out.println(info1.getCity());System.out.println(info1.getPerson().getName()+","+info1.getPerson().getAge());System.out.println("修改被复制对象中的对象引用");info1.getPerson().setName("Tom");info1.getPerson().setAge(18);System.out.println(info.getPerson().getName()+","+info.getPerson().getAge());System.out.println(info1.getPerson().getName()+","+info1.getPerson().getAge());
拷贝后,,,
Example.jerry.pratice.Info@4554617c
Example.jerry.pratice.Info@74a14482
11111
北京
jerry,23
修改被复制对象中的对象引用
Tom,18
Tom,18

结果分析:info和info1指向两个不同的对象,而两个引用info和info1中的两个person引用指向同一个对象,所以person变化时,两个同时发生了变化。即浅拷贝

clone方法存在一个缺陷,它并不会将对象的所有属性全部拷贝过来,而是有选择的拷贝。基本规则如下:

1.基本类型:拷贝其值。如int float等

2.对象:如果变量是一个实例对象,则拷贝其地址引用。即新对象和原来对象共享该实例变量。

3.String字符串:若变量为String字符串则拷贝其地址引用。但在修改时,它会从字符池中重新生成一个新的字符串,原有对象保持不变。

深拷贝

Def:深拷贝会拷贝所有的属性,并且拷贝属性指向的动态分配的内存。即对象和它所引用的对象(对象中的对象)一起拷贝就是深拷贝。相比于浅拷贝,深拷贝速度较慢且花销较大。【即,深拷贝就是把对象引用的对象都复制一份】

    public Object clone() throws CloneNotSupportedException {
//        Object object = super.clone();
//        return object;Info info1=(Info)super.clone();info1.setPerson((Person)info1.getPerson().clone());//将对象中的对象复制一份重新set//info1.person=(Person)peson.clone; 两种方式均可return info1;
}
拷贝后,,,
Example.jerry.pratice.Info@4554617c
Example.jerry.pratice.Info@74a14482
11111
北京
jerry,23
修改被复制对象中的对象引用
jerry,23
Tom,18

改写Info类中的clone方法,将Info中的Person也复制一份。可以看到修改拷贝对象中的Person对象时,原来的主对象中的person对应属性并没有改变。

【注】根据上述实例可以知道:如果要深拷贝一个对象,这个对象必须实现cloneable接口,实现clone方法,并在clone方法内部把对象引用的其他对象也要clone一份,所以被引用的对象也要实现cloneable接口和实现clone方法。

CJ:设想,如果当person中有多了一个引用对象为Hobby类,那么进行深拷贝的时候,如果还按照上述的方法,对于两个Info来说,两个独立的Info对象内的head引用已经指向了两个独立的Peson对象,但是对于这两个Person对象来说,它们指向的是同一个Hobby对象,即并没有完全的独立。要保证完全独立,也需将Person中的Hobby对象也拷贝一份。即,让Hobby类也实现Cloneable接口,实现clone方法,并在Person对象的clone方法中拷贝它所引用的Hobby对象。

class Person implements Cloneable{private String name;private int age;private Hobby hobby;protected Object clone() throws CloneNotSupportedException {//return super.clone();Person person=(Person)super.clone;peson.hobby=(Hobby)this.hobby.clone;}
}
class Hobby implements Cloneable{private String ho1;private String ho2;protected Object clone() throws CloneNotSupportedException {return super.clone();}
}

依次类推,如果Hobby对象还引用的其他的对象比如,Special,如果在Hobby类中的clone方法不处理Special的复制,Info对象拷贝之后会一级一级的引用,引用到同一个Special对象。所以要实现完全独立,只能让Special也拷贝。

如果在拷贝一个对象时,要想让这个拷贝的对象和源对象完全彼此独立,那么在引用链上的每一级对象都要被显式的拷贝。所以创建彻底的深拷贝是非常麻烦的,尤其是在引用关系非常复杂的情况下, 或者在引用链的某一级上引用了一个第三方的对象, 而这个对象没有实现clone方法, 那么在它之后的所有引用的对象都是被共享的。

Java中的浅拷贝与深拷贝相关推荐

  1. 【转】JAVA中的浅拷贝和深拷贝

    原文网址:http://blog.bd17kaka.net/blog/2013/06/25/java-deep-copy/ JAVA中的浅拷贝和深拷贝(shallow copy and deep co ...

  2. js 浅拷贝直接赋值_JS中实现浅拷贝和深拷贝的代码详解

    (一)JS中基本类型和引用类型 JavaScript的变量中包含两种类型的值:基本类型值 和 引用类型值,在内存中的表现形式在于:前者是存储在栈中的一些简单的数据段,后者则是保存在堆内存中的一个对象. ...

  3. Python中的浅拷贝和深拷贝(一看就懂!!!)

    浅拷贝和深拷贝一直傻傻的分不清,甚至有时候会理解反.今天就简单总结一下python中的浅拷贝和深拷贝. 总结 最直观的理解就是: 1.深拷贝,拷贝的程度深,自己新开辟了一块内存,将被拷贝内容全部拷贝过 ...

  4. 详解Java中的clone方法 -- 深拷贝和浅拷贝

    Java中对象的创建 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...

  5. java中浅拷贝和深拷贝_java中的浅拷贝和深拷贝

    复制 将一个对象的引用复制给另一个对象,一共有三种方式.第一种方式是直接赋值,第二种方式是浅复制,第三种方式是深复制. 1.直接赋值 在Java中,A a1 = a2,这实际上复制的是引用,也就是说 ...

  6. java深入理解浅拷贝和深拷贝

    文章目录 简介 拷贝接口 使用clone导致的浅拷贝 使用clone的深拷贝 不要overridden clone 总结 简介 拷贝对象是java中经常会遇到的问题.java中存在两种类型,基础类型和 ...

  7. 43 JavaScript中的浅拷贝与深拷贝

    技术交流QQ群:1027579432,欢迎你的加入! 欢迎关注我的微信公众号:CurryCoder的程序人生 1.浅拷贝与深拷贝 浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用. 深拷贝拷贝多层,每 ...

  8. 说说JS中的浅拷贝与深拷贝

    outline: 为什么要说JS中深拷贝与浅拷贝 JS对类型的分类 immutable与mutable 简单类型检测 浅拷贝VS深拷贝 为什么要说JS中深拷贝与浅拷贝 近来在研读underscore的 ...

  9. C#中的浅拷贝和深拷贝

    C#中有两种类型变量,一种是值类型变量,一种是引用类型变量.对于前者,copy是属于全盘复制:而对于后者,一般的copy只是浅copy,相当于只传递一个引用指针一样.因此对于后者进行真正copy的时候 ...

最新文章

  1. 拼多多java开发一面、二面合并面经
  2. sudoers修改_Ubuntu修改sudoers文件导致sudo命令无法使用的拯救方法
  3. 笔记-项目范围管理-需求工程-需求分类
  4. oracle事务处理 自动提交
  5. matlab可达性分析,毕业论文 Petri网系统的可达性研究
  6. Hive 高级编程??深入浅出学Hive
  7. 《C++语言基础》实践参考——友元类
  8. java----连接池C3p0使用的补充
  9. Win XP必须禁止的服务
  10. awk:split()函数、数组、自定义函数
  11. kali实战-被动信息收集
  12. Flutter实战一Flutter聊天应用(十一)
  13. SqlServer发布订阅错误收集
  14. java汉字转拼音区别多音字_Java中汉字转拼音pinyin4j用法实例分析
  15. 网络安全系列-X: TCP/IP协议及报文格式详解
  16. 三年开发转行测试没人要
  17. pads生成bom表
  18. vs2015下载路径
  19. 【论文合集】2022年12月医学影像期刊论文合集
  20. 1046错误mysql_数据库实例:如何解决mysql 1046错误

热门文章

  1. 数据持久化(六)之Using CoreData with MagicalRecord
  2. eclipse中如何将java项目转为java Web项目
  3. Microsoft Build 2015
  4. mysql的常用函数
  5. SQL2005CLR函数扩展-正则表达式
  6. k-d tree算法的研究
  7. git 覆盖本地修改_Git拉力–如何使用Git覆盖本地更改
  8. react 快速上手开发_React中测试驱动开发的快速指南
  9. chatscript_如何使用ChatScript构建您的第一个聊天机器人
  10. javascript优缺点_为什么要在JavaScript中使用静态类型? 优缺点