java中的深拷贝与浅拷贝

学习设计模式之原型模式时,认识了深复制与浅复制。
java中的Object类中,有一个clone()方法,它用于生成一个新的对象,当然如果我们要调用这个方法,java要求我们的类必须先实现一个Cloneable接口,此接口没有定义任何方法,但要是不实现,在clone()的时候,会抛出cloneNotSupportedException异常。

java 的克隆是浅克隆,碰到对象引用的时候,克隆出来的对象和原对象中的引用将指向同一个对象。通常实现深克隆的方法是将对象进行序列化,然后再进行反序列化。

先看浅拷贝:

public class WorkExperience {
   private String workDate;
   private String company;
public String getWorkDate() {
	return workDate;
}
public void setWorkDate(String workDate) {
	this.workDate = workDate;
}
public String getCompany() {
	return company;
}
public void setCompany(String company) {
	this.company = company;
}
   
}
-----------------------
public class Prototype implements Cloneable{
	 private String name;
	 private String sex;
	 private String age;
	 private WorkExperience work;//这是引用类型
	 public Prototype(String name) {
		 this.name = name;
		 work = new WorkExperience();
	 }
	 //设置个人信息
	 public void serPersonalInfo(String sex,String age) {
		 this.sex = sex;
		 this.age = age;
	 }
	 //设置工作经历
	 public void setWorkExperience(String workDate,String company) {
		 work.setWorkDate(workDate);
		 work.setCompany(company);
	 }
	 //显示
	 public void Display() {
		 System.out.println("姓名:"+name+" 性别:"+sex+" 年龄:"+age);
		 System.out.println("工作经历:"+work.getWorkDate()+"-"+work.getCompany());
	 }
	 public Object Clone() throws CloneNotSupportedException {
		 return this.clone();
	 }
}
----------------------
public class Test {
 public static void main(String[] args) throws CloneNotSupportedException {
	Prototype type1 = new Prototype("大牛");
	type1.serPersonalInfo("男", "29");
	type1.setWorkExperience("2010-2015", "阿里");
	
	Prototype type2 = (Prototype)type1.Clone();
	type1.setWorkExperience("2016-2020", "腾讯");
	
	Prototype type3 = (Prototype)type1.Clone();
	type3.setWorkExperience("2021-2030", "百度");
	
	type1.Display();
	System.out.println("---------------");
	type2.Display();
	System.out.println("----------------");
	type3.Display();
 }
}
运行结果:
姓名:大牛 性别:男 年龄:29
工作经历:2021-2030-百度
---------------
姓名:大牛 性别:男 年龄:29
工作经历:2021-2030-百度
----------------
姓名:大牛 性别:男 年龄:29
工作经历:2021-2030-百度

可以看到运行结果中,三次工作经历都是最后一次设置的值,这就是浅拷贝,被复制对象的所有变量都含有与原来对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。
深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

深拷贝实现:

public class WorkExperience implements Cloneable {
   private String workDate;
   private String company;
public String getWorkDate() {
	return workDate;
}
public void setWorkDate(String workDate) {
	this.workDate = workDate;
}
public String getCompany() {
	return company;
}
public void setCompany(String company) {
	this.company = company;
}
  //工作经历类也实现Cloneable接口,调用object的clone()方法
 public Object Clone() throws CloneNotSupportedException {
	 return this.clone();
 }
}
------------------------------
public class Prototype implements Cloneable{
	 private String name;
	 private String sex;
	 private String age;
	 private WorkExperience work;
	 public Prototype(String name) {
		 this.name = name;
		 work = new WorkExperience();
	 }
	 //提供Clone方法调用的私有构造函数,以便克隆“工作经历”的数据
	 private Prototype(WorkExperience work) throws CloneNotSupportedException {
		 this.work = (WorkExperience)work.Clone();
	 }
	 //设置个人信息
	 public void serPersonalInfo(String sex,String age) {
		 this.sex = sex;
		 this.age = age;
	 }
	 //设置工作经历
	 public void setWorkExperience(String workDate,String company) {
		 work.setWorkDate(workDate);
		 work.setCompany(company);
	 }
	 //显示
	 public void Display() {
		 System.out.println("姓名:"+name+" 性别:"+sex+" 年龄:"+age);
		 System.out.println("工作经历:"+work.getWorkDate()+"-"+work.getCompany());
	 }
//	 public Object Clone() throws CloneNotSupportedException {
//		 return this.clone();
//	 }
	 //调用私有的构造方法,让“工作经历”克隆完成,然后在给Prototype对象的相关字段赋值,最终返回一个深复制的简历对象
	 public Object Clone() throws CloneNotSupportedException {
		 Prototype obj = new Prototype(this.work);
		 obj.name = this.name;
		 obj.sex = this.sex;
		 obj.age = this.age;
		 return obj;
	 }
}
---------------------------------
public class Test {
 public static void main(String[] args) throws CloneNotSupportedException {
	Prototype type1 = new Prototype("大牛");
	type1.serPersonalInfo("男", "29");
	type1.setWorkExperience("2010-2015", "阿里");
	
	Prototype type2 = (Prototype)type1.Clone();
	type2.setWorkExperience("2016-2020", "腾讯");
	
	Prototype type3 = (Prototype)type1.Clone();
	type3.serPersonalInfo("女","16");
	type3.setWorkExperience("2021-2030", "百度");
	
	type1.Display();
	System.out.println("---------------");
	type2.Display();
	System.out.println("----------------");
	type3.Display();
	
 }
}
运行结果:
姓名:大牛 性别:男 年龄:29
工作经历:2010-2015-阿里
---------------
姓名:大牛 性别:男 年龄:29
工作经历:2016-2020-腾讯
----------------
姓名:大牛 性别:女 年龄:16
工作经历:2021-2030-百度

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值