Java的clone方法效率问题

  在Java中,经常会需要新建一个对象,很多情况下,需要这个新建的对象和现有的某个对象保持属性一致。

  那么,就有两种方式来实现这个对象的构造:

    ①通过新建一个对象,为这个对象的属性根据原有对象的属性来进行赋值

    ②调用clone方法,来实现实例对象的克隆

  对于Java的clone方法,需要注意的就是它实际上是一种“浅克隆”(Shallow Clone),对于int、double这种基本数据类型,直接拷贝值;对于String这样的类对象,则是直接拷贝引用。因此对于通过clone得到的对象来说,它很大程度上还是和原有被克隆对象之间有着很大的联系(例如修改clone对象的String属性,则原有对象的String属性也会变化)。

  于是,为了得到两个完全“独立”的具有相同属性的实例对象,就涉及到“深克隆”(Deep Clone)。至于如何来编写实现“深克隆”,可参考这篇博客(来自大学同学分享): https://blog.csdn.net/zhangjg_blog/article/details/18369201

  当然,至此要说明的重点并不是如何实现“深克隆”和“浅克隆”,而是要比较一下上面提到的①②两种方法,哪种效率更高一些。

  情况一: 首先,对于“浅克隆”来进行测试:

  注:这里的SimpleTest类只包含一个name属性(String型),而Test类则包括name以及line0~line9这11个属性(均为String型)。这里让这些属性值在构造器中完成初始化。

  测试代码:

  说明: 这里分别对四种情况进行测试:

    1). 简单的“浅克隆”,通过用SimpleTest的“浅克隆”来进行测试 

    2). 简单的“构造”,通过用SimpleTest的构造器来实例对象,其name值,直接通被克隆对象的name值来获取

    3). 复杂的“浅克隆”,通过Test的“浅克隆”来进行测试

    4). 复杂的“构造”,通过正常构造Test,来获得Test实例,需要注意的就是,此时Test的构造器内涉及到一系列的new操作(代表复杂构造操作)

  测试结果:

 

  结果说明: 

    ①对于轻量型的类对象,通过new操作来构造,效率会更高(对比987ms和7ms)。

    ②对于重量型的类对象,通过clone操作来进行构造,效率会更高(对比1016ms和4503ms)。

  原因分析:

    ①对于轻量型的类对象,通过new操作即可很快地进行构造,而clone方法依旧涉及到new操作,但其会进行更多的方法调用,执行流程会消耗一些时间

    ②对于重量型的类对象,new操作则需要构造相当多的对象,从而会消耗很多时间;但clone方法(这里是“浅克隆”)只需要拷贝引用给新的对象即可,因此消耗的时间会更少

  但是,这只是对于“浅克隆”来说,clone的构造效率会更高,但对于“深克隆”来说,情况却并不乐观。

  首先,按照前面提到的那篇博客,来进一步构造深克隆:

class Person implements Cloneable {
    public int age;
    public String name;
    public Body body;

    public Person(int age, String name, Body body) {
        this.age = age;
        this.name = name;
        this.body = body;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person newPerson = (Person)super.clone();
        newPerson.body = (Body)body.clone();
        return newPerson;
    }
}

class Body implements Cloneable {
    public Head head;

    public Body(Head head) {
        this.head = head;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Body newBody = (Body)super.clone();
        newBody.head = (Head)head.clone();
        return newBody;
    }
}

class Head implements Cloneable {
    public Face face;

    public Head(Face face) {
        this.face = face;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Head newHead = (Head)super.clone();
        newHead.face = (Face)face.clone();
        return newHead;
    }

}

class Face implements Cloneable {
    public Mouth mouth;

    public Face(Mouth mouth) {
        this.mouth = mouth;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Face newFace = (Face)super.clone();
        newFace.mouth = (Mouth)mouth.clone();
        return newFace;
    }
}

class Mouth implements Cloneable {
    public Tooth tooth;

    public Mouth(Tooth tooth) {
        this.tooth = tooth;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Mouth newMouth = (Mouth)super.clone();
        newMouth.tooth = (Tooth)tooth.clone();
        return newMouth;
    }
}

class Tooth implements Cloneable {
    public final int number;

    public Tooth(int number) {
        this.number = number;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
Deep Clone

  测试代码:

  按照这个结构,深克隆得到的对象和原有对象的关系如图:

 

猜你喜欢

转载自www.cnblogs.com/stevenshen123/p/9081118.html
今日推荐