您的位置:首页 > 编程语言 > Java开发

Java中的深复制与浅复制问题

2015-12-24 10:29 417 查看
在使用原型设计模式的时候,如果我们的原型类,往往都实现了clonable接口,并覆盖了clone方法;

重新生成一个新的对象;这个方法的底层是Object对象的clone方法,他是一个native方法,他直接操作的是JVM的内存;

即生成对象不通过对象所在类的构造函数;直接复制对应的内存中的东西;

在copy过程中,基本数据类型(及包装类也算),不变类型的数据;都是深度copy,什么意思呢?就是不将源对象中非基本类型成员变量的引用交给

clone的副本,使得副本中的非基本数据类型成员和源对象使用的是不同的对象;并且相互之间操作互不影响;

我们的做法是:

实现对象深复制的方法一:
package com.lrq.copy;

public class User implements Cloneable{

public User() {

System.out.println("user");

}

private String username;

private int age;

private Integer length;

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Integer getLength() {

return length;

}

public void setLength(Integer length) {

this.length = length;

}

private Account account;

public Account getAccount() {

return account;

}

public void setAccount(Account account) {

this.account = account;

}

//必须要覆盖, 为如果不覆盖的话,父类的protected方法,到了子类就是private的了;对于外部不可用;

@Override

protected Object clone() throws CloneNotSupportedException {

//copy一个新的东西出来;

User clone = (User) super.clone();

//将非基本数据类型的数据也copy一份过来;注意必须要copy.

clone.setAccount((Account) this.getAccount().clone());

return clone;

}

}

package com.lrq.copy;

public class Account implements Cloneable{

public Account() {

System.out.println("account");

}

private String id;

private Float money;

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public Float getMoney() {

return money;

}

public void setMoney(Float money) {

this.money = money;

}

@Override

protected Object clone() throws CloneNotSupportedException {

// TODO Auto-generated method stub

return super.clone();

}

}

这样就实现了源对象和copy对象直接使用互不干扰:

测试代码:
@Test

public void test() throws Exception{

User user=new User();

Account account=new Account();

account.setId("ssss");

account.setMoney(23f);

user.setAccount(account);

user.setAge(20);

user.setLength(111);

User clone = (User) user.clone();

Account account2 = clone.getAccount();

System.out.println(account2.getMoney()+"--clone");

clone.getAccount().setMoney(9999f);

System.out.println(user.getAccount().getMoney());

}

输出结果:user的account还是之前的23;而不是修改后的9999;

这里的核心是不让clone对象获取到源对象中,非基本数据类型的成员变量的引用;

处理方式二:

package com.lrq.copy;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

public class Person implements Serializable{

private static final long serialVersionUID = -8954779984792810004L;

private String id;

private String name;

private Card card;

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Card getCard() {

return card;

}

public void setCard(Card card) {

this.card = card;

}

@Override

protected Object clone(){

ByteArrayOutputStream bos=new ByteArrayOutputStream();

try {

ObjectOutputStream objectOut=new ObjectOutputStream(bos);

objectOut.writeObject(this);

ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());

ObjectInputStream objectIn=new ObjectInputStream(bis);

return objectIn.readObject();

} catch (IOException e) {

e.printStackTrace();

throw new RuntimeException(e);

} catch (ClassNotFoundException e) {

e.printStackTrace();

throw new RuntimeException(e);

}

}

}

package com.lrq.copy;

import java.io.Serializable;

public class Card implements Serializable{

private static final long serialVersionUID = -6258840793361311762L;

private String id;

private String no;

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getNo() {

return no;

}

public void setNo(String no) {

this.no = no;

}

}

测试代 :

@Test

public void test2(){

Person person=new Person();

Card card=new Card();

card.setId("ooo");

card.setNo("xxx");

person.setCard(card);

person.setId("afdaf");

person.setName("dfadffaf");

Person clone = (Person) person.clone();

clone.getCard().setNo("aaaaaaaaaaaa");

System.out.println(clone.getCard().getNo()+"clone");

System.out.println(person.getCard().getNo()+"perosn");

}

完全没问题,建议使用第二种;



转发至微博
 



转发至微博
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: