Java实践(四)---关于clone

来源:互联网 发布:金坷垃淘宝 编辑:程序博客网 时间:2024/06/09 13:44

当拷贝一个变量是,原始变量与拷贝变量引用同一个对象,改变一个变量所引用的对象将会对另一个变量产生影响

因此需要一种新的机制,克隆:默认的克隆操作是浅拷贝,它并没有克隆包含在对象中的内部对象

  1. 如果对象中的所有数据域都属于数值或基本类型,这样的克隆没有问题
  2. 如果对象中包含了子对象的引用,克隆的结果会使得2个域指向同一个子对象,因此源对象和克隆对象共享这部分信息

对于第一种情况:

  • 如果原始对象与浅拷贝对象共享的子对象是不可变的,将不会产生任何问题
  • 子对象在其生命周期内不会发生变化,既没有更改它们的方法,也没有创建对它引用的方法

对于每一个类实现克隆前必须的判断:

  1. 默认的clone方法是否满足要求
  2. 默认的clone方法是否能够通过调用可变子对象的clone得到修补
  3. 是否不应该使用clone

对于第一第二个判断,都必须实现Cloneable接口,使用public访问修饰符重新定义clone方法

子类只能调用protected的clone方法克隆它自己,为此,必须重新定义clone方法,并将它声明为public,这样才能够让所有的方法克隆对象
并不能理解这句话 尴尬!!!

Cloneable接口是Java提供的几个标记接口,标记接口没有方法,使用它的唯一目的是可以使用instanceof进行类型检查。如果一个对象需要克隆,而没有实现Cloneable接口,就好产生一个已检查异常(checked exception)

1. 默认的克隆(浅拷贝)
及时clone的是默认实现能够满足需求,也应该实现Clonea接口,将clone重新定义为public,并调用super.clone():

public class Employee implements Cloneable{     @Override    public Employee clone() throws CloneNotSupportedException {        return (Employee)super.clone();    }}

2. 深拷贝
为了实现深拷贝,必须克隆所有可变的实例域

public class Employee implements Cloneable{     @Override    public Employee clone() throws CloneNotSupportedException {        Employee cloned = (Employee)super.clone()        clined.hireDay = (Date) hireDay.clone();        return cloned;    }}

只要在clone中含有没有实现Cloneable接口的对象,Object类的clone方法就会抛出一个CloneNotsupportException异常

必须谨慎地实现子类的克隆
一旦为父类定义了clone方法,任何人都可以利用它克隆子类对象:

  • 如果子类中只有基本类型或不可变对象,那么不存在问题
  • 如果存在可变对象或者没有实现cloneable接口的对象,必须深拷贝

Tips:所以的数组都实现了clone方法,这个方法被设为public

原创粉丝点击