本文转载自点击打开链接
需求
实现一个打印简历信息的程序。
实现
级别1
public class Resume { private String name; private String sex; private String age; private String timeArea; private String company; public Resume(String name) { this.name = name; } public void setPersonalInfo(String sex, String age) { this.sex = sex; this.age = age; } public void setWorkExperience(String timeArea, String company) { this.timeArea = timeArea; this.company = company; } public void display() { System.out.println(name + " " + sex + " " + age); System.out.println("工作经历:" + timeArea + " " + company); } }
public class Main { public static void main(String[] args) { Resume a = new Resume("大鸟"); a.setPersonalInfo("男", "29"); a.setWorkExperience("1998-2000", "XX公司"); Resume b = new Resume("大鸟"); b.setPersonalInfo("男", "29"); b.setWorkExperience("1998-2000", "XX公司"); Resume c = new Resume("大鸟"); c.setPersonalInfo("男", "29"); c.setWorkExperience("1998-2000", "XX公司"); a.display(); b.display(); c.display(); } }每一份简历需要实例化,这样的客户端代码很麻烦。如果我写错了一个字,比如98年改成99年,那就要改20次。
public class Resume implements Cloneable { private String name; private String sex; private String age; private String timeArea; private String company; public Resume(String name) { this.name = name; } public void setPersonalInfo(String sex, String age) { this.sex = sex; this.age = age; } public void setWorkExperience(String timeArea, String company) { this.timeArea = timeArea; this.company = company; } public void display() { System.out.println(name + " " + sex + " " + age); System.out.println("工作经历:" + timeArea + " " + company); } public Resume clone() { try { return (Resume) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } }
public class Main { public static void main(String[] args) { Resume a = new Resume("大鸟"); a.setPersonalInfo("男", "29"); a.setWorkExperience("1998-2000", "XX公司"); Resume b = a.clone(); b.setWorkExperience("1998-2006", "YY企业"); Resume c = a.clone(); c.setPersonalInfo("男", "24"); a.display(); b.display(); c.display(); } }Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:一是拷贝对象返回的是一个新对象,而不是一个引用。二是拷贝对象与用new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。 每new一次,都需要执行一次构造函数,如果构造函数的执行时间很长,那么多次的执行这个初始化操作就实在是太低效了。一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高。
级别3
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 Resume implements Cloneable { private String name; private String sex; private String age; private WorkExperience work = new WorkExperience(); public Resume(String name) { this.name = name; } public void setPersonalInfo(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 Resume clone() throws CloneNotSupportedException { return (Resume) super.clone(); } }
public class Main { public static void main(String[] args) throws CloneNotSupportedException { Resume a = new Resume("大鸟"); a.setPersonalInfo("男", "29"); a.setWorkExperience("1998-2000", "XX公司"); Resume b = a.clone(); b.setWorkExperience("1998-2006", "YY企业"); Resume c = a.clone(); c.setWorkExperience("1998-2003", "ZZ企业"); a.display(); b.display(); c.display(); } }运行这个程序,输出是:
大鸟 男 29
工作经历:1998-2003 ZZ企业
大鸟 男 29
工作经历:1998-2003 ZZ企业
大鸟 男 29
工作经历:1998-2003 ZZ企业
由于clone是浅表复制,所以对于值类型,没什么问题,但是对于引用类型,就只是复制了引用,对引用的对象还是指向了原来的对象,所以就会出现我给a、b、c三个引用设置‘工作经历’,但却同时看到三个引用都是最后的设置是一样的,因为这三个引用都指向了同一个对象。但我们可能更需要这样的一种需求,把要复制的对象所引用的对象都复制一遍。比如刚才的例子,我们希望是a、b、c三个引用的对象都是不同的,复制时就一变二,二变三,此时,我们就叫这种方式为‘深复制’,深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。
级别4
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 WorkExperience clone() { try { return (WorkExperience) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } }
public class Resume implements Cloneable { private String name; private String sex; private String age; private WorkExperience work = new WorkExperience(); public Resume(String name) { this.name = name; } public void setPersonalInfo(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 Resume clone() { Resume obj = new Resume(name); obj.sex = this.sex; obj.age = this.age; obj.work = work.clone(); return obj; } }
public class Main { public static void main(String[] args) throws CloneNotSupportedException { Resume a = new Resume("大鸟"); a.setPersonalInfo("男", "29"); a.setWorkExperience("1998-2000", "XX公司"); Resume b = a.clone(); b.setWorkExperience("1998-2006", "YY企业"); Resume c = a.clone(); c.setWorkExperience("1998-2003", "ZZ企业"); a.display(); b.display(); c.display(); } }
运行这个程序,输出是:
大鸟 男 29
工作经历:1998-2000 XX公司
大鸟 男 29
工作经历:1998-2006 YY企业
大鸟 男 29
工作经历:1998-2003 ZZ企业
//原型类 public class Prototype implements Cloneable { private String id; public Prototype(String id) { this.id = id; } public String getId() { return this.id; } public Prototype clonePrototype() { return null; } } //具体原型类 public class ConcretePrototype1 extends Prototype { public ConcretePrototype1(String id) { super(id); } public Prototype clonePrototype() { try { return (Prototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } } //客户端代码 public class Main { public static void main(String[] args) { ConcretePrototype1 p1 = new ConcretePrototype1("I"); ConcretePrototype1 c1 = (ConcretePrototype1) p1.clonePrototype(); System.out.println("Cloned:" + c1.getId()); } }