浅复制:被复制对象的所有基本数据类型变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。
深复制:被复制对象的所有基本数据类型变量都含有与原来的对象相同的值,并且引用对象的变量指向复制过的新对象,而不是原来被引用的对象。
下面,通过简历复制的例子来理解深复制和浅复制的概念
定义一个简历类Resume.java 实现Cloneable接口,并重新Object 类的clone()方法
public class Resume implements Cloneable{
private String name;
private String birthday;
private String sex;
private String school;
private WorkExperience workExperience;
/**
* 构造函数
* 初始化简历赋值姓名
* 实例化工作经历
*/
public Resume(String name){
this.name = name;
workExperience = new WorkExperience();
}
/**
* @desc 设定个人基本信息
* @param birthday 生日
* @param sex 性别
* @param school 毕业学校
* @return void
*/
public void setPersonInfo(String birthday,String sex,String school){
this.birthday = birthday;
this.sex = sex;
this.school = school;
}
/**
* @desc 设定工作经历
* @param workDate 工作年限
* @param company 所在公司
* @return void
*/
public void setWorkExperience(String workDate,String company){
workExperience.setWorkDate(workDate);
workExperience.setCompany(company);
}
/**
* 克隆该实例
*/
public Object clone(){
Resume resume = null;
try {
resume = (Resume) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return resume;
}
public void display(){
System.out.println("姓名:" + name);
System.out.println("生日:" + birthday + ",性别:" + sex + ",毕业学校:" + school);
System.out.println("工作年限:" + workExperience.getWorkDate() + ",公司:" + workExperience.getCompany());
}
}
定义一个工作经历类WorkExperience.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;
}
}
客户端类Client.java
public class Client {
public static void main(String[] args){
//原型对象A
Resume a = new Resume("小王");
a.setPersonInfo("2.16", "男", "辽宁大学");
a.setWorkExperience("2011.07.05", "辽宁科技有限公司");
//克隆对象B
Resume b = (Resume) a.clone();
//修改B对象的个人信息
b.setPersonInfo("8.19", "女", "河北大学");
//修改B对象的工作经历
b.setWorkExperience("2012.09.15","河北科技有限公司");
//输出A和B对象
System.out.println("----------------A--------------");
a.display();
System.out.println("----------------B--------------");
b.display();
}
}
运行结果
从结果中可以看到,克隆出来的B对象成功的修改了自己的个人信息,却没有修改A对象的个人信息;而B对象修改工作经历中的公司名称时,A对象中的公司名称也被修改了。
因为工作经历是一个引用类型,采用上述方法复制出来的B对象中的工作经历workexpericence变量是一个引用,它与A对象的引用指向同一个工作经历对象,因此修改B对象的工作经历A对象的工作经历也会改变。这便是浅复制的表现。
下面我们对刚刚的代码做一些修改。
修改工作经历类 WorkExperience.java,使其实现Cloneable接口,并重写Object的clone()方法
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;
}
public Object clone(){
WorkExperience workExperience = null;
try {
workExperience = (WorkExperience) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return workExperience;
}
}
在简历类Resume.java的clone()方法中,添加一行调用WorkExperience的clone()方法的代码
public class Resume implements Cloneable{
private String name;
private String birthday;
private String sex;
private String school;
private WorkExperience workExperience;
/**
* 构造函数
* 初始化简历赋值姓名
* 实例化工作经历
*/
public Resume(String name){
this.name = name;
workExperience = new WorkExperience();
}
/**
* @desc 设定个人基本信息
* @param birthday 生日
* @param sex 性别
* @param school 毕业学校
* @return void
*/
public void setPersonInfo(String birthday,String sex,String school){
this.birthday = birthday;
this.sex = sex;
this.school = school;
}
/**
* @desc 设定工作经历
* @param workDate 工作年限
* @param company 所在公司
* @return void
*/
public void setWorkExperience(String workDate,String company){
workExperience.setWorkDate(workDate);
workExperience.setCompany(company);
}
/**
* 克隆该实例
*/
public Object clone(){
Resume resume = null;
try {
resume = (Resume) super.clone();
this.workExperience = (WorkExperience)workExperience.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return resume;
}
public void display(){
System.out.println("姓名:" + name);
System.out.println("生日:" + birthday + ",性别:" + sex + ",毕业学校:" + school);
System.out.println("工作年限:" + workExperience.getWorkDate() + ",公司:" + workExperience.getCompany());
}
}
客户类Client.java不做改动
运行结果
分析结果可知,我们修改了B对象的工作经历对A对象并未产生影响。这便是深复制的表现。
(声明:本文为个人学习笔记,观点非原创。如有问题,欢迎讨论。)