Java中的深复制、浅复制

//******************************** 两个对象指向同一内存堆 start *********************************

public class Client_v1 {

Student s1=new Student(1,"LMGD",9);

Student s2=s1;//使得两个对象指向同一内存堆

 

//s2.setNum(222);//s1、s2的num属性都会变成 222 因为 两个对象指向同一内存堆

System.out.println(s1);

System.out.println(s2);

System.out.println(s1==s2);//true 说明 两个对象指向同一内存堆

System.out.println(s1.equals(s2));//true

}

//******************************** 两个对象指向同一内存堆 start *********************************

//******************************** 浅复制 start *********************************

一般步骤是(浅复制):

1. 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常) 该接口为标记接口(不含任何方法)

2. 覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象,(native为本地方法)

public class Person implements Cloneable{

private int num;

private String name;

private int age;

private Address addr;//引用类型

public Person(int num, String name, int age) {

   this.num = num;

   this.name = name;

   this.age = age;

}

/***

@Override

protected Object clone() throws CloneNotSupportedException {

     return super.clone();

}

**/

//也可以这样子

@Override

public Object clone() { // 重写的话:不可以降低访问权限(所以 可以扩大访问权限 从 protected ---> public )             

        Person p= null;

        try{

             p= (Person)super.clone();

           }catch(CloneNotSupportedException e) {

             e.printStackTrace(); } return p;

         }

}

测试:

public class Client_v2 {

    public static void main(String[] args) throws CloneNotSupportedException {

//克隆

Person p1 = new Person(1, "LMGD", 8);

Address addr=new Address("中国上海");

p1.setAddr(addr);

Person p2 = (Person) p.clone();

 

System.out.println("sb 1号:" + p1);

System.out.println("sb 2号:" + p2);

//p2.getAddr.set

 

// Person 克隆了,而 Address没有克隆

System.out.println(p1==p2);//false 说明指向不同的内存空间

p2.setNum(9999);//只改变 p2的num属性,因为 p 和 p2 指向的不是一个内存推

//如果字段是引用类型:则复制引用但不复制引用的对象。 --摘抄自<大话设计模式>

System.out.println(p1.getAddr()==p2.getAddr());//true ,Address没有克隆 指向的是同一内存地址。

 }

}

//******************************** 浅复制 end *********************************

 

//******************************* 深度复制(deep copy) start ********************************

 public class Person implements Cloneable {

private int num;

private String name;

private int age;

 

private Address addr;

 

public Person(int num, String name, int age) {

this.num = num;

this.name = name;

this.age = age;

}

  @Override

  protected Object clone() {

Person p = null;

try {

   p = (Person) super.clone();//浅复制 (注:因为addr属性 是引用类型)

    p.addr = (Address) addr.clone(); //深度复制

 } catch (CloneNotSupportedException e) {

    e.printStackTrace();

}

          return p;

}

//....省略get/set

}

public class Address implements Cloneable {

   private String add;

   @Override

   public Object clone() {

Address addr = null;

try {

  addr = (Address) super.clone();

} catch (CloneNotSupportedException e) {

   e.printStackTrace();

}

 return addr;

}

//....省略get/set

}

//测试

public class Client_v3 {

    public static void main(String[] args) {

Address addr=new Address();

addr.setAdd("上海市");

 

Person per1=new Person(1,"LMGD",100);

per1.setAddr(addr);

Person per2 =(Person) per1.clone();

 

System.out.println(per1);

System.out.println(per2);

 

//addr.setAdd("宝山区");(与 per1.getAddr().setAdd("宝山区"); 意思一样 )

 

//只改变per1 的addr属性,如果 Address 对象 不克隆,那么 对象 per1、per2 的addr 属性  的值都会变

per1.getAddr().setAdd("宝山区");                                                        

System.out.println(per1);

System.out.println(per2);

 

System.out.println(per1==per2); //false 指向不同内存你地址

 

//指向不同内存你地址,所以 per1的addr属性值变了, per2 的 addr的值不会跟着变

System.out.println(per1.getAddr()==per2.getAddr()); //false

//疑问:不太理解 为什么不克隆 那么输出的就是一样的,克隆了就会输出 不一样????

回答:  1.  a.Person 、Address 都克隆后 per1、与 per2 指向的是不同的内存地址(内存堆)

               b. per1 的 addr 与 克隆出来的 per2 里面的 addr属性,指向的是不同的内存地址

               c. 所以 addr 属性值改变时,并不会 影响 per2 里面的 addr属性值。

 2 .Person 克隆、而Address 不克隆 那么 per1、per2 对象的属性 addr指向的都是是同一个引用,

     addr指向的都是同一内存地址,所以 addr改变了,

     per1、per2 对象的 addr的值就会一起变。

// 输出内容:

// Person{num=1, name='LMGD', age=100, addr=Address{add='上海市'}}

// Person{num=1, name='LMGD', age=100, addr=Address{add='上海市'}}

// Person{num=1, name='LMGD', age=100, addr=Address{add='宝山区'}}

// Person{num=1, name='LMGD', age=100, addr=Address{add='上海市'}}

 

// 如果 Address 对象 不 克隆 输出的就是

// Person{num=1, name='LMGD', age=100, addr=Address{add='上海市'}}

// Person{num=1, name='LMGD', age=100, addr=Address{add='上海市'}}

// Person{num=1, name='LMGD', age=100, addr=Address{add='宝山区'}}

// Person{num=1, name='LMGD', age=100, addr=Address{add='宝山区'}}

   }

}

//******************************* 深度复制(deep copy) start *********************************

注:谢谢 http://www.cnblogs.com/dolphin0520/p/3700693.html

猜你喜欢

转载自blog.csdn.net/LMGD_/article/details/82801230