【Java】clone

来源:互联网 发布:网络飞机票怎么取登机 编辑:程序博客网 时间:2024/06/13 08:55

在java世界里,大致有四种创建对象的方法。new,clone,反射和序列化。

这里研究下clone方法。为什么需要这个方法?已经有其他的三种创建方式了。因为如果我们想要创建一个和原有对象完全一样的对象,使用clone更方便。为什么不直接new一个对象,然后手动赋一样的值呢?因为JVM为这个clone的需求提供了更加高效的办法,java底层直接有native的办法实现在内存级别clone对象,这样肯定比我们new赋值更快,这就是需要clone的原因。

值得注意的是,clone方法是在object根类中实现的,本质是一个native方法,而且是protected的,也就是说只能在子类中调用。在外部是无法调用的。这是一点。第二点,要想实现一个类具有clone功能,必须让它实现cloneable接口,这个接口本质上没有任何方法,他只是一个标示接口,让jvm知道这个类是可以clone的,如果不实现接口运行时报错。为什么clone方法不在cloneable接口内部呢?很简单,因为这个方法是jvm要提供一个默认实现的,如果放入接口,那么就无法提供默认实现,每一类都需要自行实现。而每个类的对象都应该能使用jvm的默认实现,于是就放在了object类中。

对于java中已有的类,往往无法使用clone方法,因为protected属性,那如果要使用怎么办?我觉得只能继承一下,然后实现cloneable接口,重写clone方法,设置为public的,才行。那如果有类是final呢?比如stringbuffer?那就没办法了,无法使用,只能通过new关键字创建新对象。

我们自定义的类要具有clone,那么就需要注意之前的两点,即实现接口和设置public。

在自定义类还需要注意深浅拷贝,如果直接调用object的clone是浅拷贝,对于引用类型只是赋值不复制,如果要深拷贝,就需要在super.clone的基础上,对每一个引用属性再调用其clone方法,所以属性也需要clone的设计,这个过程会一直形成一个链子,我们需要根据实际情况来维护这个深拷贝链条。

package test;class Age implements Cloneable{int age;public Age clone() throws CloneNotSupportedException {return (Age) super.clone();}}public class Pro implements Cloneable{Age age;int a;public Pro(Age age) {this.age = age;System.out.println("con");}public Pro clone() throws CloneNotSupportedException {return (Pro) super.clone();//Pro copy = (Pro) super.clone();//copy.age = this.age.clone();//return copy;}public static void main(String args[]) {Age age = new Age();Pro pro = new Pro(age);System.out.println(pro.age.age);try {Pro copy = pro.clone();copy.age.age = 100;System.out.println(pro.age.age);} catch (CloneNotSupportedException e) {e.printStackTrace();}}}