参考文章:http://blog.csdn.net/XIAXIA__/article/details/41652057

解决问题:深拷贝、浅拷贝 和普通的对象赋值有什么区别?

对象复制

例如:Person p2 = p1;实质就是对象地址复制。把p1地址赋值给p2。此时二者同时指向一块堆内存,所以改变p1的属性值之后,p2所对应的属性值也会跟着变化。

例如有一个如下所示的Person类:

 package tudou.javabasic.clone;

 class Person {
private int age;
private String name;
private Address address; public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
} public Person(int age, String name) {
this.age = age;
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}

Person

执行如下代码:

 public class CloneTest {
public static void main(String[] args) {
Person p1 = new Person(1, "first");
Person p2 = p1;//把p1的引用赋值给p2
System.out.println("p2.name before:"+p2.getName());
p1.setName("second");
System.out.println("p2.name after:"+p2.getName());
}
}

CloneTest

输出结果为:

p2.name before:first
p2.name after:second

如果在改变p1的值之后不想改变p2的值,应该如何处理呢?这时候需要用到拷贝,拷贝用到的函数为object的clone()方法

深拷贝和浅拷贝

clone()方法:

创建一个新对象,然后将当前对象的非静态字段复制到该新对象,
如果字段是值类型的,那么对该字段执行复制;
如果该字段是引用类型的话,则复制引用但不复制引用的对象。(这个称为浅拷贝)
原始对象及其副本引用同一个对象。
这个也就是说:如果使用clone()方法,对于值类型直接复制,对于引用类型 则还是采用复制 引用地址的方式。
代码如下:
 package tudou.javabasic.clone;

 /**
* Created by tudou on 2017-02-22.
* 浅拷贝
*/
public class ShallowCopyPerson implements Cloneable {
private int age;
private String name;
private Address address; public ShallowCopyPerson(int age, String name, Address address) {
this.age = age;
this.name = name;
this.address = address;
}
public Object clone() {
try {
return (ShallowCopyPerson)super.clone();
} catch (Exception e) {
e.printStackTrace();
return null;
}
} public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "ShallowCopyPerson{" +
"age=" + age +
", name='" + name + '\'' +
", address=" + address +
'}';
}
}

ShallowCopyPerson

ShallowCopyPerson 类扩展Cloneable接口,重点关注的方法是clone()方法,这里只是简单使用:

 public Object clone() {
try {
return (ShallowCopyPerson)super.clone();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

接下来使用ShallowCopyPerson 类,来观察下列代码的运行结果:

 //对象浅拷贝
private static void shallowCopyTest() {
Address address = new Address("Henan", "zhoukou");
ShallowCopyPerson shallowCopyPerson = new ShallowCopyPerson(
18,
"tudou",
address
);
ShallowCopyPerson personClone = (ShallowCopyPerson) shallowCopyPerson.clone();
System.out.println("personClone info before:" + personClone.toString());
System.out.println("shallowCopyPerson info before:" + shallowCopyPerson.toString());
//这里改变原 shallowCopyPerson的值
shallowCopyPerson.setName("new tudou");
shallowCopyPerson.setAge(19);
//改变address的地址值
address.setCity("fj");
address.setProvince("fz");
shallowCopyPerson.setAddress(address);
System.out.println("personClone info after:" + personClone.toString());
System.out.println("shallowCopyPerson info before:" + shallowCopyPerson.toString());
}

shallowCopyTest

结果如下:

 ersonClone info before:ShallowCopyPerson{age=18, name='tudou', address=Address{province='Henan', city='zhoukou'}}
shallowCopyPerson info before:ShallowCopyPerson{age=18, name='tudou', address=Address{province='Henan', city='zhoukou'}}
personClone info after:ShallowCopyPerson{age=18, name='tudou', address=Address{province='fz', city='fj'}}
shallowCopyPerson info before:ShallowCopyPerson{age=19, name='new tudou', address=Address{province='fz', city='fj'}}
从结果可以看到:age和name字段 在原对象shallowCopyPerson的属性改变之后 personclone并未改变。但是,address中的字段province和city均有改变!这种方式属于浅拷贝,即clone()方法是浅拷贝。
如何使得address中的字段值也不改变呢?就需要用到深拷贝。
 package tudou.javabasic.clone;

 /**
* Created by tudou on 2017-02-22.
* 深拷贝
*/
public class DeepCopyPerson implements Cloneable {
private int age;
private String name;
private Address address; public DeepCopyPerson(int age, String name, Address address) {
this.age = age;
this.name = name;
this.address = address;
}
public Object clone() {
try {
return (DeepCopyPerson)super.clone();
} catch (Exception e) {
e.printStackTrace();
return null;
}
} public Address getAddress() {
return address;
} public void setAddress(String province, String city) {
address = new Address(province,city);
address.setCity(city);
address.setProvince(province);
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "ShallowCopyPerson{" +
"age=" + age +
", name='" + name + '\'' +
", address=" + address +
'}';
}
}

DeepCopyPerson

运行下面代码:

     //对象深拷贝
private static void deepCopyTest() {
Address address = new Address("Henan", "zhoukou");
DeepCopyPerson deepCopyPerson = new DeepCopyPerson(
18,
"tudou",
address
);
DeepCopyPerson personClone = (DeepCopyPerson) deepCopyPerson.clone();
System.out.println("personClone info before:" + personClone.toString());
//这里改变原 shallowCopyPerson的值
deepCopyPerson.setName("new tudou");
deepCopyPerson.setAge(19);
//改变address的地址值
// address.setCity("zhengzhou");
deepCopyPerson.setAddress("fj","fz");
System.out.println("personClone info after:" + personClone.toString());
}

deepCopyTest

结果如下:

personClone info before:ShallowCopyPerson{age=18, name='tudou', address=Address{province='Henan', city='zhoukou'}}
personClone info after:ShallowCopyPerson{age=18, name='tudou', address=Address{province='Henan', city='zhoukou'}}

可以看到这里值完全没有改变。这里实现的深拷贝只是简单的来实现效果,不做效率方面的考虑。

总结

对象赋值:把一个对象的地址复制给另一个对象,二者都指向堆栈中的地址。所以一个对象中的值变了,另一个也会变。

浅拷贝:对于基本类型,克隆对象和原对象相互独立,没有影响,对于引用类型,复制的还是地址值,所以一个改变了,另一个也会改变。

深拷贝:原对象和克隆对象相互独立,不受影响。


java对象拷贝和复制的更多相关文章

  1. JAVA 对象拷贝

    1.java里的clone分为:  A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象.  b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍.  Java中对 ...

  2. java对象实现深复制的方法

    p2 = (Person)org.apache.commons.lang3.ObjectUtils.cloneBean(p); Person p2 = new Person(); p2 = (Pers ...

  3. Java对象拷贝备忘

    列举 //cglib net.sf.cglib.beans.BeanCopier.create net.sf.cglib.beans.BeanCopier.copy //spring-beans or ...

  4. java 对象之间的复制

    package com.jy.demo.web; import java.util.Date; public class People { private String name;//姓名 priva ...

  5. Java 对象拷贝方式

    (1)BeanUtils.cloneBean()使用: http://www.cnblogs.com/fervour/archive/2009/12/18/1627868.html package c ...

  6. Java Object 对象拷贝

    Java Object 对象拷贝 @author ixenos JAVA 对象拷贝 Java里的clone分为:  1.浅拷贝:浅复制仅仅复制所考虑的对象,而不复制它所引用的对象,Object类里的c ...

  7. 通过与C++程序对比,彻底搞清楚JAVA的对象拷贝

    目录 一.背景 二.JAVA对象拷贝的实现 2.1 浅拷贝 2.2 深拷贝的实现方法一 2.3 深拷贝的实现方法二 2.3.1 C++拷贝构造函数 2.3.2 C++源码 2.3.3 JAVA通过拷贝 ...

  8. Java对象和集合的拷贝/克隆/复制

    昨天同事遇到了一个奇怪的问题,他需要将一个JavaBean拷贝一份,然后对新创建的Bean进行操作.但是他对新的Bean操作后,会影响旧的Bean的值.当听到这个问题的时候,我第一反应就是他的拷贝方法 ...

  9. Java提高篇——对象克隆(复制)

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

随机推荐

  1. cmd启动,重启,停止IIS命令

    直接使用CMD我们可以操作很多事情,比如启动IIS,重启IIS,停止IIS 重启IIS服务器,开始->运行->cmd (以下列出相关操作命令): iisreset /RESTART 停止后 ...

  2. oracle状态

    Oracle_四种状态 oracle四种状态 1.shutdown(完全关闭) 2.nomount(未加载) 3.mount(已加载) 4.open(完全打开) Shutdown状态 Shutdown ...

  3. 【转载】Retina屏的移动设备如何实现真正1px的线?

    文章转载自 酷勤网 http://www.kuqin.com/ 原文链接:http://www.kuqin.com/shuoit/20150530/346322.html 原文摘要:前些日子总被人问起 ...

  4. Windows 10 快捷键汇总表格

    Windows 10 快捷键汇总表格 Windows 10 快捷键汇总 Win键 + Tab 激活任务视图 Win键 + A 激活操作中心 Win键 + C 通过语音激活Cortana Win键 + ...

  5. win10 uwp 应用转后台清理内存

    我在写小说阅读器,把每个打开的文件的内容读到内存,因为小说都很小,所以放在内存不怕太大,但是我如果打开了一本小说,再打开一本,我不会把先打开的小说的内容清除掉,在内存.所以一旦我打开多小说的时候,内存 ...

  6. JAVA提高八:动态代理技术

    对于动态代理,学过AOP的应该都不会陌生,因为代理是实现AOP功能的核心和关键技术.那么今天我们将开始动态代理的学习: 一.引出动态代理 生活中代理应该是很常见的,比如你可以通过代理商去买电脑,也可以 ...

  7. ReflectiveLoader分析(远程线程注入 PE修正)

    从github上下载了ReflectiverLoader认真学习了一下 在代码中得到一些心得和自己的想法,都按步骤写到了代码中,现在分享给大家,如有错,望大家指正 其中需要注入的dll和解析, 内存R ...

  8. 异步API

    整合到一起,作为参考: //2 5 3 4 1 //2 5 3 1 4 var img = new Image(); img.src = '.'; img.onerror = function() { ...

  9. 笔记-测试崩溃之memcpy_s

    昨天晚上提测,今天早上测试发来贺电,程序崩溃!!!!!! 而问题出在memcpy_s errno_t memcpy_s( void *dest, size_t numberOfElements, co ...

  10. java语言编写杨辉三角

    package com.llh.demo; /** * 杨辉三角 * * @author llh * */ public class Test { /* * 杨辉三角 */ public static ...