黑马程序员技术交流社区

标题: 【广州】【原创】浅克隆 和深度克隆 [打印本页]

作者: yqw_gz_java    时间: 2019-12-3 14:14
标题: 【广州】【原创】浅克隆 和深度克隆
本帖最后由 yqw_gz_java 于 2019-12-3 15:07 编辑

在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。这里就要用到java中克隆的知识了.
克隆包括:浅克隆  和深度克隆
一 :如果 A对象的组成都是基本数据类型,只要浅克隆即可.
尺寸类:
[Java] 纯文本查看 复制代码
package cn.yqw.shallowclone;

/**
* @author: 杨钦炜
* @mail 4024081418@qq.com
* @create: 2019-12-03 14:47
*/
public class Measurement implements Cloneable {

    public int length;
    public int width;

    public Measurement(int length, int width) {
        this.length = length;
        this.width = width;
    }

    @Override
    public String toString() {
        return "Measurement{" +
                "length=" + length +
                ", width=" + width +
                '}';
    }

    @Override
    protected Measurement clone() {
        Measurement clone = null;
        try {
            clone = (Measurement) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return clone;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }
}

测试类:
[Java] 纯文本查看 复制代码
package cn.yqw.shallowclone;

/**
* @author: 杨钦炜
* @mail 4024081418@qq.com
* @create: 2019-12-03 14:52
*/
public class Test1 {


    public static void main(String[] args) {
        Measurement m1 = new Measurement(10, 20);
        Measurement  m2 =  m1.clone();
        m2.length=128;
        m2.width=100;
        System.out.println("m2:==>"+m2);
        System.out.println("m1:==>"+m1);

    }
}

输出效果:
[AppleScript] 纯文本查看 复制代码
C:\java8\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\lib\idea_rt.jar=2098:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\bin" -Dfile.encoding=UTF-8 -classpath C:\java8\jre\lib\charsets.jar;C:\java8\jre\lib\deploy.jar;C:\java8\jre\lib\ext\access-bridge-64.jar;C:\java8\jre\lib\ext\cldrdata.jar;C:\java8\jre\lib\ext\dnsns.jar;C:\java8\jre\lib\ext\jaccess.jar;C:\java8\jre\lib\ext\jfxrt.jar;C:\java8\jre\lib\ext\localedata.jar;C:\java8\jre\lib\ext\nashorn.jar;C:\java8\jre\lib\ext\sunec.jar;C:\java8\jre\lib\ext\sunjce_provider.jar;C:\java8\jre\lib\ext\sunmscapi.jar;C:\java8\jre\lib\ext\sunpkcs11.jar;C:\java8\jre\lib\ext\zipfs.jar;C:\java8\jre\lib\javaws.jar;C:\java8\jre\lib\jce.jar;C:\java8\jre\lib\jfr.jar;C:\java8\jre\lib\jfxswt.jar;C:\java8\jre\lib\jsse.jar;C:\java8\jre\lib\management-agent.jar;C:\java8\jre\lib\plugin.jar;C:\java8\jre\lib\resources.jar;C:\java8\jre\lib\rt.jar;C:\Users\yqw\IdeaProjects\jishutie\target\classes cn.yqw.shallowclone.Test1
m2:==>Measurement{length=128, width=100}
m1:==>Measurement{length=10, width=20}
Process finished with exit code 0

从上面测试效果来看,两个对象已经是互不影响了,接着看下面的列子
现在有学生类,和地址类,clone 一个学生,然后修改地址对象
学生类代码如下:
[Java] 纯文本查看 复制代码
package cn.yqw.clone;

/**
* @author: 杨钦炜
* @mail 4024081418@qq.com
* @create: 2019-12-03 13:56
*/
public class Student implements Cloneable {

    public String studentname;
    public Address address;

    public Student(String studentname, Address address) {
        this.studentname = studentname;
        this.address = address;
    }

    @Override
    protected Student clone(){

        Student clone = null;
        try {
            clone = (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return clone;
    }


    @Override
    public String toString() {
        return "Student{" +
                "studentname='" + studentname + '\'' +
                ", address=" + address +
                '}';
    }
}

地址类代码如下:
[Java] 纯文本查看 复制代码
package cn.yqw.clone;

/**
* @author: 杨钦炜
* @mail 4024081418@qq.com
* @create: 2019-12-03 13:57
*/
public class Address  {
    /**
     * 简要
     */
    public String brief;
    /**
     * 详情
     */
    public String details;


    public Address(String brief, String details) {
        this.brief = brief;
        this.details = details;
    }



    @Override
    public String toString() {
        return "Address{" +
                "brief='" + brief + '\'' +
                ", details='" + details + '\'' +
                '}';
    }
}

测试类代码如下
[Java] 纯文本查看 复制代码
package cn.yqw.clone;

/**
* @author: 杨钦炜
* @mail 4024081418@qq.com
* @create: 2019-12-03 13:58
*/
public class Test {

    public static void main(String[] args) {
        Student student = new Student("学生一",new Address("湖南","湖南省邵阳市新宁县丰田乡"));
        Student clone = student.clone();
        System.out.println(clone);

        clone.address.brief="广州";
        clone.address.details="广东省广州市天河区";

        System.out.println("-----------------------------------");
        System.out.println("clone:===>"+clone);
        System.out.println("student:===>"+student);


    }
}

输出效果
Student{studentname='学生一', address=Address{brief='湖南', details='湖南省邵阳市新宁县丰田乡'}}
-----------------------------------
clone:===>Student{studentname='学生一', address=Address{brief='广州', details='广东省广州市天河区'}}
student:===>Student{studentname='学生一', address=Address{brief='广州', details='广东省广州市天河区'}}

从上面的测试来看,对学生二做修改影响到了学生一,这不是我们想要的结果,接下来就要用我深度克隆来解决这个问题
修改地址类:
[Java] 纯文本查看 复制代码
package cn.yqw.clone;

/**
* @author: 杨钦炜
* @mail 4024081418@qq.com
* @create: 2019-12-03 13:57
*/
public class Address   implements  Cloneable{
    /**
     * 简要
     */
    public String brief;
    /**
     * 详情
     */
    public String details;


    public Address(String brief, String details) {
        this.brief = brief;
        this.details = details;
    }


    @Override
    protected Address  clone()  {
        Address clone = null;
        try {
            clone = (Address) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }

    @Override
    public String toString() {
        return "Address{" +
                "brief='" + brief + '\'' +
                ", details='" + details + '\'' +
                '}';
    }
}

学生类修改如下:
[Java] 纯文本查看 复制代码
package cn.yqw.clone;

/**
* @author: 杨钦炜
* @mail 4024081418@qq.com
* @create: 2019-12-03 13:56
*/
public class Student implements Cloneable {

    public String studentname;
    public Address address;

    public Student(String studentname, Address address) {
        this.studentname = studentname;
        this.address = address;
    }

    @Override
    protected Student clone() {

        Student clone = null;
        try {
            clone = (Student) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        clone.address = clone.address.clone();
        return clone;
    }


    @Override
    public String toString() {
        return "Student{" +
                "studentname='" + studentname + '\'' +
                ", address=" + address +
                '}';
    }
}


测测试结果:
[AppleScript] 纯文本查看 复制代码
Student{studentname='学生一', address=Address{brief='湖南', details='湖南省邵阳市新宁县丰田乡'}}
-----------------------------------
clone:===>Student{studentname='学生一', address=Address{brief='广州', details='广东省广州市天河区'}}
student:===>Student{studentname='学生一', address=Address{brief='湖南', details='湖南省邵阳市新宁县丰田乡'}}

总结:当被克隆的对象存在引用类型的属性,就要用到深度克隆.


















欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2