用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.
之所以需要重写Cloneable的clone方法,因为方法访问修饰符是protected,外界没办法调用,这里用到 浅克隆
//原型 public class Prototype implements Cloneable{ private String name; private String sex; private String age; private String timeArea; private String company; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getTimeArea() { return timeArea; } public void setTimeArea(String timeArea) { this.timeArea = timeArea; } public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public Prototype(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+"--年龄:"+age+"--性别:"+sex); System.out.println("工作经历:"+timeArea+"--"+company); } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }; }
入口main
public class Test { public static void main(String[] args) throws Exception { Prototype pro = new Prototype("小甜甜"); pro.SetPersonalInfo("女", "21"); pro.SetWorkExperience("2000-01-01", "天朝软件"); Prototype pro1 = (Prototype)pro.clone(); //一下输出,这不是同一个对象 //System.out.println(pro!=pro1); pro1.SetPersonalInfo("男", "22"); pro1.SetWorkExperience("2000-01-01", "地府软件"); pro1.Display(); pro.Display(); } }
以下引用Heart.X.Raid的Java深浅克隆
Java支持克隆
既然如此,难道我们就没有办法在某一个类的作用域外部来克隆这个类了吗?
答案是否定的! 我们可以在任何一个类中重写clone方法,并升级它的访问作用域。事实上,使用的时候也就是这样做的!
首先我们必须在需要克隆的类上实现一个重要的接口——Cloneable接口。这种接口我们叫作 标记接口(tagging interface) 。这种标记接口没有任何方法,唯一的作用就是作为一个标志,用来告诉JVM一个类是否具有某个特定的功能。
如此一来,我们只要定义一个具有 Clone 功能的类就可以了:
1. 在类的声明中加入“ implements Cloneable ”,标志该类有克隆功能;
2. 重载类 Object 的 clone() 方法,在该方法中调用 super.clone() :
class Employee implements Cloneable{ public Object clone() throws CloneNotSupportedException{//重载clone()方法 Employee cloned=(Employee)super.clone(); return cloned; } } class Employee implements Cloneable{ public Object clone() throws CloneNotSupportedException{//重载clone()方法 Employee cloned=(Employee)super.clone(); return cloned; } }
深Clone和浅Clone
拷贝副本的问题并没有完全解决。clone技术并不是那么简单的。Object中的clone()方法是对具体类对象的各个域进行对应的赋值。如果具体类对象中还有子对象,这个问题就复杂了。
// 具备浅克隆的Employee类 class Employee implements Cloneable{ public String name=""; public Date hireDay=null; public Object clone(){ Employee cloned=(Employee)super.clone(); return cloned; } } Employee orignal=new Employee(); Employee copy=orignal.copy();
对于上面的代码,克隆以后orignal与copy中的hireDay指向的是同样的存储位置。也就是说当我们调用copy.hireDay.setTime()方法后,orignal中的hireDay也会发生改变。但String类(由于常量池的存储方式)和基本数据类型变量时不会改变的。这种对子对象克隆无效的方式我们叫做 浅克隆 。
很多情况下,我们需要将对象中的所有域(包括子对象)都进行真正的克隆。要做到这种深克隆,我们必须在重载clone()方法时克隆子对象:
//具备深度克隆功能的Employee类 class Employee implement Cloneable{ public String name=""; private Date hireDay=null; public Object clone(){ Employee cloned=(Employee)super.clone(); //浅克隆 cloned.hireDay=(Date)hireDay.clone(); //克隆子对象 return cloned; } }