java 复制字段_java对象拷贝和复制

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

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

对象复制

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

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagetudou.javabasic.clone;2

3 classPerson {4 private intage;5 privateString name;6 privateAddress address;7

8 publicAddress getAddress() {9 returnaddress;10 }11

12 public voidsetAddress(Address address) {13 this.address =address;14 }15

16 public Person(intage, String name) {17 this.age =age;18 this.name =name;19 }20

21 public intgetAge() {22 returnage;23 }24

25 public void setAge(intage) {26 this.age =age;27 }28

29 publicString getName() {30 returnname;31 }32

33 public voidsetName(String name) {34 this.name =name;35 }36

37 @Override38 publicString toString() {39 return "Person{" +

40 "age=" + age +

41 ", name='" + name + '\'' +

42 '}';43 }44 }

Person

执行如下代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public classCloneTest {2 public static voidmain(String[] args) {3 Person p1 = new Person(1, "first");4 Person p2 = p1;//把p1的引用赋值给p2

5 System.out.println("p2.name before:"+p2.getName());6 p1.setName("second");7 System.out.println("p2.name after:"+p2.getName());8 }9 }

CloneTest

输出结果为:

p2.name before:first

p2.name after:second

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

深拷贝和浅拷贝

clone()方法:

创建一个新对象,然后将当前对象的非静态字段复制到该新对象,

如果字段是值类型的,那么对该字段执行复制;

如果该字段是引用类型的话,则复制引用但不复制引用的对象。(这个称为浅拷贝)

原始对象及其副本引用同一个对象。

这个也就是说:如果使用clone()方法,对于值类型直接复制,对于引用类型 则还是采用复制 引用地址的方式。

代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagetudou.javabasic.clone;2

3 /**

4 * Created by tudou on 2017-02-22.5 * 浅拷贝6 */

7 public class ShallowCopyPerson implementsCloneable {8 private intage;9 privateString name;10 privateAddress address;11

12 public ShallowCopyPerson(intage, String name, Address address) {13 this.age =age;14 this.name =name;15 this.address =address;16 }17 publicObject clone() {18 try{19 return (ShallowCopyPerson)super.clone();20 } catch(Exception e) {21 e.printStackTrace();22 return null;23 }24 }25

26 publicAddress getAddress() {27 returnaddress;28 }29

30 public voidsetAddress(Address address) {31 this.address =address;32 }33

34 public intgetAge() {35 returnage;36 }37

38 public void setAge(intage) {39 this.age =age;40 }41

42 publicString getName() {43 returnname;44 }45

46 public voidsetName(String name) {47 this.name =name;48 }49

50

51 @Override52 publicString toString() {53 return "ShallowCopyPerson{" +

54 "age=" + age +

55 ", name='" + name + '\'' +

56 ", address=" + address +

57 '}';58 }59 }

ShallowCopyPerson

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

1 publicObject clone() {2 try{3 return (ShallowCopyPerson)super.clone();4 } catch(Exception e) {5 e.printStackTrace();6 return null;7 }8 }

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 //对象浅拷贝

2 private static voidshallowCopyTest() {3 Address address = new Address("Henan", "zhoukou");4 ShallowCopyPerson shallowCopyPerson = newShallowCopyPerson(5 18,6 "tudou",7 address8 );9 ShallowCopyPerson personClone =(ShallowCopyPerson) shallowCopyPerson.clone();10 System.out.println("personClone info before:" +personClone.toString());11 System.out.println("shallowCopyPerson info before:" +shallowCopyPerson.toString());12 //这里改变原 shallowCopyPerson的值

13 shallowCopyPerson.setName("new tudou");14 shallowCopyPerson.setAge(19);15 //改变address的地址值

16 address.setCity("fj");17 address.setProvince("fz");18 shallowCopyPerson.setAddress(address);19 System.out.println("personClone info after:" +personClone.toString());20 System.out.println("shallowCopyPerson info before:" +shallowCopyPerson.toString());21 }

shallowCopyTest

结果如下:

1 ersonClone info before:ShallowCopyPerson{age=18, name='tudou', address=Address{province='Henan', city='zhoukou'}}2 shallowCopyPerson info before:ShallowCopyPerson{age=18, name='tudou', address=Address{province='Henan', city='zhoukou'}}3 personClone info after:ShallowCopyPerson{age=18, name='tudou', address=Address{province='fz', city='fj'}}4 shallowCopyPerson info before:ShallowCopyPerson{age=19, name='new tudou', address=Address{province='fz', city='fj'}}

从结果可以看到:age和name字段 在原对象shallowCopyPerson的属性改变之后 personclone并未改变。但是,address中的字段province和city均有改变!这种方式属于浅拷贝,即clone()方法是浅拷贝。

如何使得address中的字段值也不改变呢?就需要用到深拷贝。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagetudou.javabasic.clone;2

3 /**

4 * Created by tudou on 2017-02-22.5 * 深拷贝6 */

7 public class DeepCopyPerson implementsCloneable {8 private intage;9 privateString name;10 privateAddress address;11

12 public DeepCopyPerson(intage, String name, Address address) {13 this.age =age;14 this.name =name;15 this.address =address;16 }17 publicObject clone() {18 try{19 return (DeepCopyPerson)super.clone();20 } catch(Exception e) {21 e.printStackTrace();22 return null;23 }24 }25

26 publicAddress getAddress() {27 returnaddress;28 }29

30 public voidsetAddress(String province, String city) {31 address = newAddress(province,city);32 address.setCity(city);33 address.setProvince(province);34 }35

36 public intgetAge() {37 returnage;38 }39

40 public void setAge(intage) {41 this.age =age;42 }43

44 publicString getName() {45 returnname;46 }47

48 public voidsetName(String name) {49 this.name =name;50 }51

52

53 @Override54 publicString toString() {55 return "ShallowCopyPerson{" +

56 "age=" + age +

57 ", name='" + name + '\'' +

58 ", address=" + address +

59 '}';60 }61 }

DeepCopyPerson

运行下面代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 //对象深拷贝

2 private static voiddeepCopyTest() {3 Address address = new Address("Henan", "zhoukou");4 DeepCopyPerson deepCopyPerson = newDeepCopyPerson(5 18,6 "tudou",7 address8 );9 DeepCopyPerson personClone =(DeepCopyPerson) deepCopyPerson.clone();10 System.out.println("personClone info before:" +personClone.toString());11 //这里改变原 shallowCopyPerson的值

12 deepCopyPerson.setName("new tudou");13 deepCopyPerson.setAge(19);14 //改变address的地址值15 //address.setCity("zhengzhou");

16 deepCopyPerson.setAddress("fj","fz");17 System.out.println("personClone info after:" +personClone.toString());18 }

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'}}

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

总结

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值