克隆对象
- 概念
- 浅复制和深复制
- 类图
- 代码实例
概念
原型模式就是我们常常接触的克隆,为了更高效更快的创建对象,无须再进行通过new来创建对象并初始化对象数据,直接通过拷贝内存的对象结构(浅复制),拷贝对象结构和数据(深度复制)进行创建对象。
科普下,记得之前面试的时候被问知道那些创建对象的方式:
1、new 构造方法进行创建
2、反序列化方式
3、clone克隆
4、反射,cls.getConstructor().newInstance() 如果构造方法有参数 cls.getConstructor(Class type).newInstance(具体对应类型参数值)
浅复制和深复制
浅复制:复制对象数据结构,仅仅拷贝对象引用,也就是所有克隆对象中的引用类型的属性都会指向同个对象
深度复制:复制对象结构和数据(并不仅仅拷贝对象引用,而且还要重新clone引用的对象)
注意需要考虑是否有循环引用的问题,假如类A包含类B 类B包含类C 而类C又包含类A 所以这样就是循环引用,如果这个要深复制就会导致clone方法一直被调用直到栈溢出
类图
代码实例
WorkExperience 工作经历类
/**
* @author duanyimiao
* @create 2018-09-23 4:51 PM
* @description 工作经验类
**/
public class WorkExperience implements Cloneable {
private String company;
private String timeSpan;
public WorkExperience() {
}
public WorkExperience(String company, String timeSpan) {
this.company = company;
this.timeSpan = timeSpan;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getTimeSpan() {
return timeSpan;
}
public void setTimeSpan(String timeSpan) {
this.timeSpan = timeSpan;
}
@Override
public String toString() {
return "WorkExperience{" +
"company='" + company + '\'' +
", timeSpan='" + timeSpan + '\'' +
'}';
}
@Override
public Object clone(){
try {
return super.clone();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
ResumeByShallowCopy 浅复制的简历类
/**
* @author duanyimiao
* @create 2018-09-23 4:50 PM
* @description 简历类 浅复制 复制对象数据结构
**/
public class ResumeByShallowCopy implements Cloneable {
private String name;
private Integer age;
private WorkExperience workExperience;
public ResumeByShallowCopy() {
}
public ResumeByShallowCopy(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public WorkExperience getWorkExperience() {
return workExperience;
}
public void setWorkExperience(WorkExperience workExperience) {
this.workExperience = workExperience;
}
@Override
public String toString() {
return "ResumeByShallowCopy{" +
"name='" + name + '\'' +
", age=" + age +
", workExperience=" + workExperience +
'}';
}
/**
* clone方法是在Object类中
* 该类必须实现Cloneable接口,否则调用此方法会抛出CloneNotSupportedException异常
* @return
*/
@Override
public Object clone(){
try {
return super.clone();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
ResumeByDeepCopy 深复制简历类
/**
* @author duanyimiao
* @create 2018-09-23 4:50 PM
* @description 简历类 深度克隆 复制对象结构和数据(并不仅仅拷贝对象引用,而且还要重新clone引用的对象)
**/
public class ResumeByDeepCopy implements Cloneable {
private String name;
private Integer age;
private WorkExperience workExperience;
public ResumeByDeepCopy() {
}
public ResumeByDeepCopy(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public WorkExperience getWorkExperience() {
return workExperience;
}
public void setWorkExperience(WorkExperience workExperience) {
this.workExperience = workExperience;
}
@Override
public String toString() {
return "ResumeByDeepCopy{" +
"name='" + name + '\'' +
", age=" + age +
", workExperience=" + workExperience +
'}';
}
/**
* 深度复制,注意需要考虑是否有循环引用的问题,假如类A包含类B 类B包含类C 而类C又包含类A 所以这样就是循环引用,如果这个要深复制就会导致clone方法一直被调用直到栈溢出
*
* @return
*/
@Override
public Object clone() {
ResumeByDeepCopy resumeByDeepCopy = new ResumeByDeepCopy();
resumeByDeepCopy.age = this.age;
resumeByDeepCopy.name = this.name;
resumeByDeepCopy.workExperience = (WorkExperience) this.workExperience.clone();
return resumeByDeepCopy;
}
}
MainTest client测试类
/**
* @author duanyimiao
* @create 2018-09-23 4:54 PM
* @description
**/
public class MainTest {
public static void main(String[] args) {
//不用多次new 就可以打印多份相同的简历,此时为浅复制,也就是简历A 简历B 简历C的工作经历都是一样的,如果我想改动C简历的工作经历时,同时A和B的工作经历都会改变,这并不是我们想要的,这个就需要使用深度克隆了
System.out.println("=========浅复制");
ResumeByShallowCopy A = new ResumeByShallowCopy("dynamo");
A.setAge(18);
WorkExperience workExperience = new WorkExperience("alibaba", "2016-now");
A.setWorkExperience(workExperience);
ResumeByShallowCopy B = (ResumeByShallowCopy) A.clone();
ResumeByShallowCopy C = (ResumeByShallowCopy) A.clone();
System.out.println("A address=" + A.hashCode() + " " + "B address=" + B.hashCode() + " " + "C address=" + C.hashCode());
System.out.println("shallow copy Resume A=" + A);
System.out.println("shallow copy Resume B=" + B);
System.out.println("shallow copy Resume C=" + C);
//想修改简历C的工作经历信息
C.getWorkExperience().setTimeSpan("2016-2019");
System.out.println("shallow copy after modify workexperience Resume A=" + A);
System.out.println("shallow copy after modify workexperience Resume B=" + B);
System.out.println("shallow copy after modify workexperience Resume C=" + C);
//深度复制
System.out.println("=========深复制");
ResumeByDeepCopy A1 = new ResumeByDeepCopy("dynamo");
A1.setAge(18);
WorkExperience workExperience1 = new WorkExperience("alibaba", "2016-now");
A1.setWorkExperience(workExperience1);
ResumeByDeepCopy B1 = (ResumeByDeepCopy) A1.clone();
ResumeByDeepCopy C1 = (ResumeByDeepCopy) A1.clone();
System.out.println("A1 address=" + A1.hashCode() + " " + "B1 address=" + B1.hashCode() + " " + "C1 address=" + C1.hashCode());
System.out.println("deep copy Resume A1=" + A1);
System.out.println("deep copy Resume B1=" + B1);
System.out.println("deep copy Resume C1=" + C1);
//想修改简历C的工作经历信息
C1.getWorkExperience().setTimeSpan("2016-2019");
System.out.println("deep copy after modify workexperience Resume A1=" + A1);
System.out.println("deep copy after modify workexperience Resume B1=" + B1);
System.out.println("deep copy after modify workexperience Resume C1=" + C1);
}
}
输出结果:
=========浅复制
A address=960687909 B address=1499628417 C address=1386723327
shallow copy Resume A=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
shallow copy Resume B=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
shallow copy Resume C=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
shallow copy after modify workexperience Resume A=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-2019'}}
shallow copy after modify workexperience Resume B=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-2019'}}
shallow copy after modify workexperience Resume C=ResumeByShallowCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-2019'}}
=========深复制
A1 address=1868041274 B1 address=2106256625 C1 address=734659227
deep copy Resume A1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy Resume B1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy Resume C1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy after modify workexperience Resume A1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy after modify workexperience Resume B1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-now'}}
deep copy after modify workexperience Resume C1=ResumeByDeepCopy{name='dynamo', age=18, workExperience=WorkExperience{company='alibaba', timeSpan='2016-2019'}}