Java语言准备了用于复制实例的clone方法。要想调用clone方法,被复制对象的类必须实现java.lang.Cloneable接口,不论是被复制对象的类实现java.lang.Cloneable接口还是其某个父类实现Cloneable接口,亦或是被复制对象的类实现了Cloneable接口的子接口都可以。
实现了Cloneable接口的类的实例可以调用clone方法进行复制,clone方法的返回值是复制出的新的实例(clone方法内部所进行的处理是分配与要复制的实例同样大小的内存空间,接着将要复制的实例中的字段的值复制到所分配的内存空间中去)。
如果没有实现Cloneable接口的类的实例调用了clone方法,则会在运行时抛出CloneNotSupportedException异常。
clone方法是在哪里定义的
clone方法定义在java.lang.Object中。因为Object类是所有Java类的父类,因此所有的Java类都继承了clone方法。
需要实现Cloneable的哪些方法
提到Cloneable接口,很容易让人误以为Cloneable接口中声明了clone方法。其实这是错误的。在Cloneable接口中并没有声明任何方法。它只是被用来标记“可以使用clone方法进行复制”的。这样的接口被称为标记接口。
clone方法进行的是浅复制
clone方法所进行的复制只是将被复制实例的字段值直接复制到新的实例中。换言之,它并没有考虑字段中所保存的实例的内容。例如,当字段中保存的是数组时,如果使用clone方法进行复制,则只会复制该数组的引用,并不会一一复制数组中的元素。
像这样的字段对字段的复制被称为浅复制(shallow copy)。clone方法所进行的复制就是浅复制。
当使用clone方法进行浅复制无法满足需求时,类的设计者可以实现重写clone方法,实现自己需要的复制功能(重写clone方法时,别忘了使用super.clone()来调用父类的clone方法)。
需要注意的是,clone方法只会进行复制,并不会调用被复制实例的构造函数。此外,对于在生成实例时需要进行特殊的初始化处理的类,需要自己去实现clone方法,在其内部进行这些初始化处理。