Java对象的深层复制是指Java对象A本身被clone成新对象B,同时A的属性也是被clone成新对象,赋值到A的各个属性上去,A与B的相同属性都引用到不同的对象;

Java对象的浅层复制是指Java对象A本身被clone成新对象B,但A的属性没有被clone处理,只是把A的各个属性所指的对象赋值到B对应的属性上,A与B的相同属性都引用到同一个对象。

在java中,默认是浅层复制的,如果要复制的对象中只含有基本数据类型和String类型,

那么浅层复制和浅层复制是没有区别的,所以你可以放心的使用默认的浅层复制,

如果属性有Date或其他自定的数据类,则一定的小心了,因为这时浅层复制后对象B的属性birthday与原始对象A的对应属性birthday,都是引用到同一个对象TestVo ,

如果通过B.birthday的方法改了TestVo的值,则修改会影响到A.birthday,这时也就会发生互串的情况

以下三种方法可以实现浅层复制:

(1)通过调用对象set方法来实现,属性个数比较少时适用

public class TestVo implementsCloneable{privateString name;private intage;privateDate birthday;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}publicDate getBirthday() {returnbirthday;

}public voidsetBirthday(Date birthday) {this.birthday =birthday;

}protectedTestVo clone() {

TestVo testVo= null;try{

testVo= (TestVo) super.clone();

}catch(Exception e) {

e.printStackTrace();

}returntestVo;

}

}

public static voidtest1(){

TestVo t1= newTestVo();

t1.setAge(10);

t1.setName("刘备");

t1.setBirthday(DateUtil.strToDate("2016-10-10 12:12:12"));

TestVo t2= newTestVo();

t2.setAge(t1.getAge());

t2.setName(t1.getName());

t2.setBirthday(t1.getBirthday());

System.out.println("t1=="+t1.getAge()+","+t1.getName()+","+t1.getBirthday());

System.out.println("t2=="+t2.getAge()+","+t2.getName()+","+t2.getBirthday());

t2.setAge(20);

t2.setName("张飞");

t2.setBirthday(DateUtil.strToDate("2016-11-11 13:13:13"));

System.out.println("t3=="+t1.getAge()+","+t1.getName()+","+t1.getBirthday());

System.out.println("t4=="+t2.getAge()+","+t2.getName()+","+t2.getBirthday());

}

打印结果如下:

t1==10,刘备,Mon Oct 10 12:12:12 CST 2016

t2==10,刘备,Mon Oct 10 12:12:12 CST 2016

t3==10,刘备,Mon Oct 10 12:12:12 CST 2016

t4==20,张飞,Fri Nov 11 13:13:13 CST 2016

这时候浅层复制和深层复制打到的效果是一样的,所以对t2的值修改,不会影响t1对象的值,

但是如果date类型的属性值,按照以下方法设置值,则会影响到t1中的值

public static voidtest1(){

TestVo t1= newTestVo();

t1.setAge(10);

t1.setName("刘备");

t1.setBirthday(DateUtil.strToDate("2016-10-10 12:12:12"));

TestVo t2= newTestVo();

t2.setAge(t1.getAge());

t2.setName(t1.getName());

t2.setBirthday(t1.getBirthday());

System.out.println("t1=="+t1.getAge()+","+t1.getName()+","+t1.getBirthday());

System.out.println("t2=="+t2.getAge()+","+t2.getName()+","+t2.getBirthday());

t2.setAge(20);

t2.setName("张飞");//t2.setBirthday(DateUtil.strToDate("2016-11-11 13:13:13"));

t2.getBirthday().setTime(1000);

System.out.println("t3=="+t1.getAge()+","+t1.getName()+","+t1.getBirthday());

System.out.println("t4=="+t2.getAge()+","+t2.getName()+","+t2.getBirthday());

}

打印结果如下:

t1==10,刘备,Mon Oct 10 12:12:12 CST 2016

t2==10,刘备,Mon Oct 10 12:12:12 CST 2016

t3==10,刘备,Thu Jan 01 08:00:01 CST 1970

t4==20,张飞,Thu Jan 01 08:00:01 CST 1970

这时候t2值修改后,t1页跟着修改了,Date是一个可变的类,这样浅层复制就出现属性值互串的情况,

通过监听引用地址t1.getBirthday() == t2.getBirthday(),发现:

t2.setBirthday(DateUtil.strToDate("2016-11-11 13:13:13"));这样设置值,t1和t2的引用地址不一样,所有t2修改不会对t1产生影响

t2.getBirthday().setTime(1000);这样设置值,t1.getBirthday() == t2.getBirthday()控制台返回true,说明t1和t2的引用同一个地址,所有会相互影响,

如有不对之处,请不吝赐教,欢迎指正

(2) 通过复写object.clone来实现

TestVo t1 = newTestVo();

t1.setAge(10);

t1.setName("刘备");

t1.setBirthday(DateUtil.strToDate("2016-10-10 12:12:12"));

TestVo t2= t1.clone();

(3)通过工具类,BeanUtils, 属性个数很多时候适用

TestVo t1 = newTestVo();

t1.setAge(10);

t1.setName("刘备");

t1.setBirthday(DateUtil.strToDate("2016-10-10 12:12:12"));

TestVo t2= newTestVo();

BeanUtils.copyProperties(t2, t1);

(2)(3)和(1)的打印结果是一样的,同样,如果(2)(3)的date类型也按照如下修改值,也会影响t1的值,和(1)的一样

t2.getBirthday().setTime(1000);

再看下面的例子:

public classTestVoB {private intsex;public TestVoB(intsex){this.sex =sex;

}public voidsumValue(){this.sex += 10;

}publicString toString(){returnInteger.toString(sex);

}public intgetSex() {returnsex;

}public void setSex(intsex) {this.sex =sex;

}

}

public class TestVo implementsCloneable{privateString name;private intage;privateDate birthday;TestVoB testVoB = new TestVoB(222);publicTestVoB getTestVoB() {returntestVoB;

}public voidsetTestVoB(TestVoB testVoB) {this.testVoB =testVoB;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}publicDate getBirthday() {returnbirthday;

}public voidsetBirthday(Date birthday) {this.birthday =birthday;

}protectedTestVo clone() {

TestVo testVo= null;try{

testVo= (TestVo) super.clone();

}catch(Exception e) {

e.printStackTrace();

}returntestVo;

}

}

public static void test2() throwsCloneNotSupportedException{

TestVo t1= newTestVo();

t1.setAge(10);

t1.setName("刘备");

t1.setBirthday(DateUtil.strToDate("2016-10-10 12:12:12"));

TestVo t2=t1.clone();

System.out.println("t1=="+t1.getAge()+","+t1.getName()+","+t1.getBirthday());

System.out.println("t2=="+t2.getAge()+","+t2.getName()+","+t2.getBirthday());

t2.setAge(20);

t2.setName("张飞");

t2.setBirthday(DateUtil.strToDate("2016-11-11 13:13:13"));

t2.testVoB.sumValue();

System.out.println("t3=="+t1.getAge()+","+t1.getName()+","+t1.getBirthday()+","+t1.testVoB);

System.out.println("t4=="+t2.getAge()+","+t2.getName()+","+t2.getBirthday()+","+t2.testVoB);

}

打印结果如下:

t1==10,刘备,Mon Oct 10 12:12:12 CST 2016

t2==10,刘备,Mon Oct 10 12:12:12 CST 2016

t3==10,刘备,Mon Oct 10 12:12:12 CST 2016,232

t4==20,张飞,Fri Nov 11 13:13:13 CST 2016,232

可以看出t2中的testVoB值的修改影响了t1中的testVoB,说明两个引用指向同一个对象。

一般情况下,用浅层复制就够了,但是在特殊情况下,浅层复制不能满足我们的业务需求,这时候就需要深层复制,实现深层复制只需要在上面的例子中修改一下就可以:

1.让TestVoB 类也实现和TestVo类一样的clone功能(实现Cloneable接口,重载clone()方法),

2.在TestVo的clone()方法中加入一句testVo.testVoB = testVoB.clone();

public class TestVoB implementsCloneable{private intsex;publicTestVoB clone() {

TestVoB testVoB= null;try{

testVoB= (TestVoB) super.clone();

}catch(Exception e) {

e.printStackTrace();

}returntestVoB;

}public TestVoB(intsex){this.sex =sex;

}public voidsumValue(){this.sex += 10;

}publicString toString(){returnInteger.toString(sex);

}public intgetSex() {returnsex;

}public void setSex(intsex) {this.sex =sex;

}

}public class TestVo implementsCloneable{privateString name;private intage;privateDate birthday;

TestVoB testVoB= new TestVoB(222);publicTestVoB getTestVoB() {returntestVoB;

}public voidsetTestVoB(TestVoB testVoB) {this.testVoB =testVoB;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}publicDate getBirthday() {returnbirthday;

}public voidsetBirthday(Date birthday) {this.birthday =birthday;

}protectedTestVo clone() {

TestVo testVo= null;try{

testVo= (TestVo) super.clone();

}catch(Exception e) {

e.printStackTrace();

}

testVo.testVoB=testVoB.clone();returntestVo;

}

}

这时候再去执行,打印结果如下:

t1==10,刘备,Mon Oct 10 12:12:12 CST 2016

t2==10,刘备,Mon Oct 10 12:12:12 CST 2016

t3==10,刘备,Mon Oct 10 12:12:12 CST 2016,222

t4==20,张飞,Fri Nov 11 13:13:13 CST 2016,232

可以看到t2中的testVoB值的修改,t1中的testVoB没有变化,说明两个对象引用指向了不同的对象,实现了深层复制

以上只是本人自己的一些理解,如有不对的地方,请不吝赐教,共同学习

java浅_浅谈Java浅层复制和深层复制相关推荐

  1. java兵临城下_再谈java事件监听机制

    java中的事件机制的参与者有3种角色: 1.event object:就是事件产生时具体的"事件",用于listener的相应的方法之中,作为参数,一般存在于listerner的 ...

  2. java 枚举_深入理解Java枚举

    所有知识体系文章,[GitHub](https://github.com/Ziphtracks/JavaLearningmanual)已收录,欢迎Star!再次感谢,愿你早日进入大厂! https:/ ...

  3. java学习_都说Java难学,不知道具体的学习内容?全套Java学习路线送上

    首先,我个人比较推崇的学习方法是:先学java前段,也就是HTML,css,js,因为学习java以后肯定是往java ee方向发展的,学习完前端,在学习后端很多东西比计较容易理解! 其中J2SE是关 ...

  4. java 静态方法_新手学Java,哪些知识点可以优先掌握?

    --我们的征途是星辰是大海-- 文|达妹 很多同学在刚接触Java的时候,会有些迷茫,不知道该从哪里入手,该学习掌握哪些必要的基础知识. 达妹总结了零基础学习Java编程语言的几个基础知识要点.希望对 ...

  5. 从零开始学java 框架_从零开始学 Java - 搭建 Spring MVC 框架

    如果创建一个 Spring 项目 Spring MVC 框架在 Java 的 Web 项目中应该是无人不知的吧,你不会搭建一个 Spring 框架?作为身为一个刚刚学习Java的我都会,如果你不会的话 ...

  6. Java继承_深入理解Java继承、封装、多态的实现原理

    点击关注上方"Java技术江湖",设为"置顶或星标",第一时间送达技术干货. 作者:黄小斜 文章来源:微信公众号[Java技术江湖] 目录 从JVM结构开始谈多 ...

  7. groovy 使用java类_深入学习java中的Groovy 和 Scala 类

    前言 Java 传承的是平台,而不是语言.有超过 200 种语言可以在 JVM 上运行,它们之中不可避免地会有一种语言最终将取代 Java 语言,成为编写 JVM 程序的最佳方式.本系列将探讨三种下一 ...

  8. java翻译程序_有没有java代码翻译软件?

    展开全部 没有翻译软件,但是能32313133353236313431303231363533e78988e69d8331333365646333编写翻译程序. java 代码翻译实例: 1.输入一个 ...

  9. java安装_在线学习Java编程的最佳方法

    java安装 1.简介 Java是使用最广泛的编程语言之一. 根据Github的最新报告,Java被列为仅次于JavaScript的第二大最常用的编程语言. 掌握Java的人有很多话题. 好消息是,您 ...

  10. 安卓 java内存碎片_理解Android Java垃圾回收机制

    Jvm(Java虚拟机)内存模型 从Jvm内存模型中入手对于理解GC会有很大的帮助,不过这里只需要了解一个大概,说多了反而混淆视线. Jvm(Java虚拟机)主要管理两种类型内存:堆和非堆. 堆是运行 ...

最新文章

  1. VS2010 CUDA 5.5 Win7 64位配置以及项目创建配置
  2. 计算机网络的组成相关,计算机网络的组成
  3. 判断字符串中只含有字母和问题
  4. 新华三,定义服务器虚拟化市场新格局
  5. 安装 VMware Workstation Pro 16 并创建 ubuntu 20.04 虚拟机
  6. MySQL实验四数据库的查询_MySQL数据库实验四:嵌套查询
  7. 【Linux】一步一步学Linux——xeyes命令(228)
  8. 原始套接字与sniffer
  9. 都2020年了,这5个java IDE神器你还不知道?
  10. 201421123042 《Java程序设计》第8周学习总结
  11. 你知道source map如何帮你定位源码么?
  12. oracle job 每月前十天运行_Tensorflow源码解析7 -- TensorFlow分布式运行时
  13. es5创建对象与继承
  14. 进程间通信学习APUE学习---进程间通信(4)
  15. [eclipse error]'Android Dependencies' which does not allow modifications to source attachments on it
  16. flash 加载外部flash怎么卸载干净
  17. java实现评论功能_Java实现评论回复功能的完整步骤
  18. 计算机教师招聘10分钟试讲,小学数学教师招聘考试面试,要求是一个小时备课,试讲十分钟,怎么准备?求助各位前辈~...
  19. vue页面详情页返回列表页_vue 详情页返回列表页,保留列表页之前的筛选条件...
  20. 【安信可NB-IoT模组EC系列AT指令应用笔记④】将设备位置接入阿里云地图,实现空间数据可视化

热门文章

  1. 90后男屌丝如何让淘宝客日赚10万滴
  2. 如何在Mac OS上从Photoshop 2020作为插件访问Topaz DeNoise AI?
  3. 网页上的内容无法复制和下载?一行代码教你解决
  4. 系列篇|一文尽览事件相机原理
  5. 软件著作权申报中60页标准代码文档
  6. Scratch(五):Scratch小游戏之超级玛丽
  7. 没有oracle 连接kettle,Kettle 连接 oracle
  8. 服务器基线扫描修复,怎么对服务器进行基线和漏洞扫描
  9. 超声B mode聚焦成像仿真(ultrasound B mode fcous imaging simulation)
  10. xul界面编程语法_探索XUL中的多线程编程