栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java克隆

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java克隆

什么是克隆

java的克隆类似于对象的复制。

为什么需要克隆

想对一个对象进行处理,且保留原有的对象。
比如根据一个叫张三的学生信息,复制出李四、王五的学生信息,且保留张三的学生信息,然后组装三个学生的List。

java克隆分类

java克隆分为浅克隆与深克隆。

  1. 浅克隆:只克隆基本类型。引用类型没有克隆,只是新建一个引用,该引用仍然指向原有的对象。比如张三的学生信息中,有老师这个引用对象。克隆张三的学生信息修改成李四的信息后,老师信息并未被克隆,修改张三的老师,李四的老师也被修改。
  2. 深克隆:基本类型和引用类型都被克隆,引用类型的变量指向的是新克隆的对象。

下面上代码实例,为了保险起见,咱们上三层嵌套。Student里有Teacher,Teacher里有Course。

浅克隆
  1. Student代码
package org.ludk.clone;


public class Student implements Cloneable{
    private String name;
    private int age;
    private  Teacher teacher;

    public Student(String name, int age, Teacher teacher) {
        this.name = name;
        this.age = age;
        this.teacher = teacher;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", teacher=" + teacher +
                '}';
    }
}

  1. Teacher代码
package org.ludk.clone;


public class Teacher implements Cloneable{
    private String name;
    private int age;
    private Course course;

    public Teacher(String name, int age, Course course) {
        this.name = name;
        this.age = age;
        this.course = course;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

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

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", course=" + course +
                '}';
    }
}


  1. Course代码
package org.ludk.clone;


public class Course {
    private String name;
    private int days;

    public Course(String name, int days) {
        this.name = name;
        this.days = days;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getDays() {
        return days;
    }

    public void setDays(int days) {
        this.days = days;
    }

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

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + ''' +
                ", days=" + days +
                '}';
    }
}


  1. 测试类代码
package org.ludk.clone;


public class TestClone implements Cloneable{
    
    public static void main(String[] args) throws CloneNotSupportedException {
        //新建个学生张三
        Student student=new Student("张三",24,new Teacher("王老师",40,new Course("英语",90)));
        //克隆学生
        Student cloneStudent=(Student) student.clone();
        System.out.println("学生张三和克隆学生是否为一个老师");
        System.out.println(student.getTeacher()==cloneStudent.getTeacher());
        System.out.println("学生张三和克隆学生是否为一个课程");
        System.out.println(student.getTeacher().getCourse()==cloneStudent.getTeacher().getCourse());
        System.out.println("学生张三的信息");
        System.out.println(student);
        //克隆学生的信息
        System.out.println("克隆学生的信息");
        System.out.println(cloneStudent);
    }
}


  1. 测试类执行结果
D:workjavabinjava.exe "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2019.3.3libidea_rt.jar=62957:C:Program FilesJetBrainsIntelliJ IDEA 2019.3.3bin" -Dfile.encoding=UTF-8 -classpath D:workjavajrelibcharsets.jar;D:workjavajrelibdeploy.jar;D:workjavajrelibextaccess-bridge-64.jar;D:workjavajrelibextcldrdata.jar;D:workjavajrelibextdnsns.jar;D:workjavajrelibextjaccess.jar;D:workjavajrelibextjfxrt.jar;D:workjavajrelibextlocaledata.jar;D:workjavajrelibextnashorn.jar;D:workjavajrelibextsunec.jar;D:workjavajrelibextsunjce_provider.jar;D:workjavajrelibextsunmscapi.jar;D:workjavajrelibextsunpkcs11.jar;D:workjavajrelibextzipfs.jar;D:workjavajrelibjavaws.jar;D:workjavajrelibjce.jar;D:workjavajrelibjfr.jar;D:workjavajrelibjfxswt.jar;D:workjavajrelibjsse.jar;D:workjavajrelibmanagement-agent.jar;D:workjavajrelibplugin.jar;D:workjavajrelibresources.jar;D:workjavajrelibrt.jar;D:workspringcloud-demotargetclasses org.ludk.clone.TestClone
学生张三和克隆学生是否为一个老师
true
学生张三的信息
Student{name='张三', age=24, teacher=Teacher{name='王老师', age=40, course=Course{name='英语', days=90}}}
克隆学生的信息
Student{name='张三', age=24, teacher=Teacher{name='王老师', age=40, course=Course{name='英语', days=90}}}

Process finished with exit code 0


从上面的例子,可以看到学生信息被复制了,但是里面的Teacher信息仍然是一个,仍然是一个对象。

深克隆

深克隆有两种方法。一种是遇到属性为引用类型,则对该引用类型对象进行复制。另一种是用序列化实现深克隆。

第一种方法性能高些,但是实现起来复杂,因为对象里可能还嵌套对象。第二种方法实现起来简单,但是性能差些。

自定义深克隆
  1. 修改Student的clone方法
@Override
    protected Object clone() throws CloneNotSupportedException {
        Student cloneStudent= (Student)super.clone();
        cloneStudent.setTeacher((Teacher) this.getTeacher().clone());
        return cloneStudent;
    }
  1. 再次跑测试类的结果
D:workjavabinjava.exe "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2019.3.3libidea_rt.jar=50882:C:Program FilesJetBrainsIntelliJ IDEA 2019.3.3bin" -Dfile.encoding=UTF-8 -classpath D:workjavajrelibcharsets.jar;D:workjavajrelibdeploy.jar;D:workjavajrelibextaccess-bridge-64.jar;D:workjavajrelibextcldrdata.jar;D:workjavajrelibextdnsns.jar;D:workjavajrelibextjaccess.jar;D:workjavajrelibextjfxrt.jar;D:workjavajrelibextlocaledata.jar;D:workjavajrelibextnashorn.jar;D:workjavajrelibextsunec.jar;D:workjavajrelibextsunjce_provider.jar;D:workjavajrelibextsunmscapi.jar;D:workjavajrelibextsunpkcs11.jar;D:workjavajrelibextzipfs.jar;D:workjavajrelibjavaws.jar;D:workjavajrelibjce.jar;D:workjavajrelibjfr.jar;D:workjavajrelibjfxswt.jar;D:workjavajrelibjsse.jar;D:workjavajrelibmanagement-agent.jar;D:workjavajrelibplugin.jar;D:workjavajrelibresources.jar;D:workjavajrelibrt.jar;D:workspringcloud-demotargetclasses org.ludk.clone.TestClone
学生张三和克隆学生是否为一个老师
false
学生张三的信息
Student{name='张三', age=24, teacher=Teacher{name='王老师', age=40, course=Course{name='英语', days=90}}}
克隆学生的信息
Student{name='张三', age=24, teacher=Teacher{name='王老师', age=40, course=Course{name='英语', days=90}}}

Process finished with exit code 0

其实上面的自定义深克隆方法只是深克隆了老师的信息,课程的信息依然为浅克隆。可以自己实现,继续扩展。

java序列化实现深克隆
  1. Teacer、Student、Course都得实现java.io.Serializable接口
  2. 修改Student的clone方法
 @Override
    protected Object clone() throws CloneNotSupportedException {
        Student cloneObj = null;
        try {
            // 写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(this);
            obs.close();
            // 分配内存,写入原始对象,生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(ios);
            // 返回生成的新对象
            cloneObj = (Student) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
    }
  1. 重新跑测试类的结果
D:workjavabinjava.exe "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2019.3.3libidea_rt.jar=55660:C:Program FilesJetBrainsIntelliJ IDEA 2019.3.3bin" -Dfile.encoding=UTF-8 -classpath D:workjavajrelibcharsets.jar;D:workjavajrelibdeploy.jar;D:workjavajrelibextaccess-bridge-64.jar;D:workjavajrelibextcldrdata.jar;D:workjavajrelibextdnsns.jar;D:workjavajrelibextjaccess.jar;D:workjavajrelibextjfxrt.jar;D:workjavajrelibextlocaledata.jar;D:workjavajrelibextnashorn.jar;D:workjavajrelibextsunec.jar;D:workjavajrelibextsunjce_provider.jar;D:workjavajrelibextsunmscapi.jar;D:workjavajrelibextsunpkcs11.jar;D:workjavajrelibextzipfs.jar;D:workjavajrelibjavaws.jar;D:workjavajrelibjce.jar;D:workjavajrelibjfr.jar;D:workjavajrelibjfxswt.jar;D:workjavajrelibjsse.jar;D:workjavajrelibmanagement-agent.jar;D:workjavajrelibplugin.jar;D:workjavajrelibresources.jar;D:workjavajrelibrt.jar;D:workspringcloud-demotargetclasses org.ludk.clone.TestClone
学生张三和克隆学生是否为一个老师
false
学生张三和克隆学生是否为一个课程
false
学生张三的信息
Student{name='张三', age=24, teacher=Teacher{name='王老师', age=40, course=Course{name='英语', days=90}}}
克隆学生的信息
Student{name='张三', age=24, teacher=Teacher{name='王老师', age=40, course=Course{name='英语', days=90}}}

Process finished with exit code 0

从上面的例子可以看到,java序列化实现深克隆,那是真的深克隆。

参考

下面是引用https://www.cnblogs.com/xzwblog/p/7230788.html博客的图片

  • 浅克隆

  • 深克隆
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/332565.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号