浅克隆与深克隆
当拷贝一个变量时,原始变量与拷贝变量引用了同一个对象。那么当改变一个变量所引用的对象时,就会对另外一个变量产生影响。形象化一点说,就像某人A有一把遥控,用来控制电视,他把遥控交给了B,B用遥控来改变电视台,则对A来讲,他看的节目台也发生相应变化。 java
Employee e1 =new Employee(“John”,5000); Employee e2=e1; e2.raiseSalary(500);那么,若是咱们但愿获得一个拷贝,它与原拷贝互不影响,则就引入了克隆的概念。
Employee e2=e1.clone();这会产生一个新的Employee对象e2,它与被克隆对象e1有相同的属性。而且e2与e1互不影响。
浅克隆
clone()方法是object类的proteced方法,因为这个类对于具体类一无所知,因此只能对各个域进行拷贝。 数组
若是原始对象与拷贝对象的共享的子对象是不可变的,将不会产生任何问题。例如,
①对象中的全部数据域是数值或基本类型
②像String这样不容许改变的类
③在其生命周期中不会发生变化,既没有修改它们的方法,也没有建立对它们的引用的方法 安全
浅克隆 spa
域中包含对象的引用,则会使得克隆后的对象和之前的对象有着相同引用的域。这种只是单纯进行域的拷贝就称做浅克隆,而默认的方法就是浅克隆。 code
深克隆
可是,更为常见的状况是子对象是可变的,这就要用到深克隆了。咱们须要从新定义clone()方法。对那些非基本型别的域进行特殊的处理,例如本例中的hireDay。咱们能够从新定义clone()方法,对hireDay作特殊处理,以下代码: orm
class Employee implements Cloneable { public Employee clone() throws CloneNotSupportedException { Employee cloned = (Employee) super.clone(); cloned.hireDay = (Date) hireDay.clone();//克隆可变域 return cloned; } }
注意:在Java SE 5.0之前的版本中,clone()方法返回Object类型。
具体的实现方法是:
一、实现Cloneable接口
二、重写clone()方法,并将其声明为public
注释:在Object类中,clone()方法被声明为protected,所以不能直接经过对象调用anObject.clone()来直接克隆一个对象,而要依次克隆可变实例域。 对象
另外,每一个数组都包含了一个clone()方法,其返回值是public,而不是protected。能够利用这个方法建立包含全部数据元素拷贝的一个新数组。例如: 接口
int[] array={1,2,3,4,5}; int[] cloned=array.clone(); cloned[0]=0;//不会改变array[0]的值
另一种实现克隆的方法是Java序列化机制。二者的优缺点以下。
克隆:显得比较笨拙,尤为在可变域较多时,则要依次进行拷贝,比较麻烦。
java序列化:很容易实现,并且也很安全。但效率低。 生命周期