Java Clone 学习

Java Clone 学习

原文地址:详解Java中的clone方法

通常在Java中我们通过new关键字创建对象,代码如下:

Human human = new Human();
Human human2 = human;
System.out.println("human is :" + human);
System.out.println("human2 is :" + human2);

打印如下:

human is :TestClone$Human@6d06d69c

human2 is :TestClone$Human@6d06d69c

从结果看出human2和human指向了同一对象,从这行代码页印证了引用即是Java种的指针这一说法。

Java中创建对象的方法有很多,常见的有:

  • new 使用new关键字首先为新对象创建内存,然后使用构造函数为新对象的各个Field初始化
  • clone 首先为新对象创建内存,然后使用旧的对象的值填充新的对象的各个Field
  • readobject 首先为新对象创建内存,从流中读取数据,并填充新对象的各个Field

Clone 方法

Clone 定义在Object类中的保护方法,一个类如果要支持Clone,需要按照下面的两个步骤编写代码。

  • 重写Clone方法
  • 实现Cloneable接口 - Cloneable是一个标记接口,实现这个接口只需要在顶一类是声明即可,如果类未实现Cloneable接口,调用其Clone方法会抛出CloneNotSupportedException

一个例子:

static class Human implements Cloneable {
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public static void main(String[] args) {
    Human human1 = new Human();
    System.out.println("human is :" + human1);
    try {
        Human human2 = (Human) human1.clone();
        System.out.println("human2 is :" + human2);
    } catch (CloneNotSupportedException e) {
        System.out.println("human CloneNotSupportedException");
    }
}

运行结果为:

human is :TestClone$Human@6d06d69c

human2 is :TestClone$Human@7852e922

从运行结果看,Clone方法创建了新的对象。

深复制和浅复制

浅复制

浅复制是指为新的对象创建内存,并使用旧的对象的中的引用的值填充新的对象中引用的值,观察如下代码:

static class Human implements Cloneable {
    public Head mHead;

    public Human(Head head) {
        mHead = head;
    }

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public static void main(String[] args) {
    Human human1 = new Human(new Head());
    try {
        Human human2 = (Human) human1.clone();
        System.out.println("human1 is :" + human1);
        System.out.println("human2 is :" + human2);
        System.out.println("human1 head is :" + human1.mHead);
        System.out.println("human2 head is :" + human2.mHead);
    } catch (CloneNotSupportedException e) {
        System.out.println("human CloneNotSupportedException");
    }
}

运行结果:

human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@4e25154f

从运行结果看,Object类中Clone方法的实现为浅复制

深复制

深复制是指,为新的对象申请内存,并未其中的每个引用申请内存。将上述的代码改造如下:

static class Head implements Cloneable {
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

static class Human implements Cloneable {
    public Head mHead;

    public Human(Head head) {
        mHead = head;
    }

    public Object clone() throws CloneNotSupportedException {
        Human human = (Human) super.clone();
        human.mHead = (Head) mHead.clone();
        return human;
    }
}

public static void main(String[] args) {
    Human human1 = new Human(new Head());
    try {
        Human human2 = (Human) human1.clone();
        System.out.println("human1 is :" + human1);
        System.out.println("human2 is :" + human2);
        System.out.println("human1 head is :" + human1.mHead);
        System.out.println("human2 head is :" + human2.mHead);
    } catch (CloneNotSupportedException e) {
        System.out.println("human CloneNotSupportedException");
    }

}

结果如下:

human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e

从结果看human和head都指向了新的对象(内存)。

继续改造上述代码:

static class Face {

}

static class Head implements Cloneable {
    Face mFace;

    public Head() {
        mFace = new Face();
    }

    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

static class Human implements Cloneable {
    public Head mHead;

    public Human(Head head) {
        mHead = head;
    }

    public Object clone() throws CloneNotSupportedException {
        Human human = (Human) super.clone();
        human.mHead = (Head) mHead.clone();
        return human;
    }
}

public static void main(String[] args) {
    Human human1 = new Human(new Head());
    try {
        Human human2 = (Human) human1.clone();
        System.out.println("human1 is :" + human1);
        System.out.println("human2 is :" + human2);
        System.out.println("human1 head is :" + human1.mHead);
        System.out.println("human2 head is :" + human2.mHead);
        System.out.println("human1 face is :" + human1.mHead.mFace);
        System.out.println("human2 face is :" + human2.mHead.mFace);
    } catch (CloneNotSupportedException e) {
        System.out.println("human CloneNotSupportedException");
    }
}

运行结果如下:

human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e
human1 face is :TestClone$Face@5c647e05
human2 face is :TestClone$Face@5c647e05
从结果看face又指向了相同对象(引用),为了完成彻底的深复制,需要对Face类和Head类做如下改造:

static class Face implements Cloneable {
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

static class Head implements Cloneable {
    Face mFace;

    public Head() {
        mFace = new Face();
    }

    protected Object clone() throws CloneNotSupportedException {
        Head head = (Head) super.clone();
        head.mFace = (Face) mFace.clone();
        return head;
    }
}

结果如下:

human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e
human1 face is :TestClone$Face@5c647e05
human2 face is :TestClone$Face@33909752

结论

  1. Object类提供了Clone方法用于复制对象,
  2. 一个类如果要支持Clone,需要重写Clone方法,并实现Cloneable接口
  3. Object类的Clone实现为浅复制
  4. 为了达到深复制,对象的引用,以及其引用的引用(依次类推)都需要实现深复制
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容