//******************************** 两个对象指向同一内存堆 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 *********************************