zoukankan      html  css  js  c++  java
  • Java深浅拷贝

    浅拷贝:

    浅拷贝(同一个引用):仅仅复制所考虑的对象,而不复制它所引用的对象。

    Object类 是所有类的直接或间接父类,Object中存在clone方法,如下

    protected native Object clone() throws CloneNotSupportedException;

    如果想要使一个类的对象能够调用clone方法 ,则需要实现Cloneable接口, 并重写 clone方法:

    package copy;
    
    class Teacher implements Cloneable
    {
        private String name;
        private int age;
    
        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;
        }
    
    }
    
    class Student2 implements Cloneable {
        private String name;
        private int age;
        private 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
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    public class CopyTest {
        public static void main(String[] args) throws CloneNotSupportedException {
            Teacher teacher = new Teacher();
            teacher.setName("Delacey");
            teacher.setAge(29);
    
            Student2 student1 = new Student2();
            student1.setName("Dream");
            student1.setAge(18);
            student1.setTeacher(teacher);
    
            Student2 student2 = (Student2) student1.clone();
    
            System.out.println("拷贝后");
            System.out.println(student2.getName());//Dream
            System.out.println(student2.getAge());//18
            System.out.println(student2.getTeacher().getName());//Delacey
            System.out.println(student2.getTeacher().getAge());//29
    
            System.out.println("修改老师的信息后------");
            // 修改老师的信息
            teacher.setName("Jam");
            System.out.println(student1.getTeacher().getName());//Jam
            System.out.println(student2.getTeacher().getName());//Jam
    
            System.out.println("修改拷贝后的学生信息后与被拷贝学生信息对比------");
            student2.setName("MerGy");
            System.out.println(student1.getName());//Dream
            System.out.println(student2.getName());//MerGy
        }
    }

    深拷贝:

    深拷贝会拷贝独立对象所有的属性,并拷贝属性指向的内存。深拷贝会把要复制的对象和引用的对象都拷贝,所以,深拷贝相比于浅拷贝速度较慢并且花销较大。

    package copy;
    
    class Teacher2 implements Cloneable {
        private String name;
        private int age;
    
        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;
        }
    
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    class Student3 implements Cloneable {
        private String name;
        private int age;
        private Teacher2 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 Teacher2 getTeacher() {
            return teacher;
        }
        public void setTeacher(Teacher2 teacher) {
            this.teacher = teacher;
        }
    
        @Override
        public Object clone() throws CloneNotSupportedException {
            // 浅复制时:
            // return super.clone();
    
            // 改为深复制:
            Student3 student = (Student3) super.clone();
            // 本来是浅复制,现在将Teacher对象复制一份并重新set进来
            student.setTeacher((Teacher2) student.getTeacher().clone());
            return student;
        }
    
    }
    
    public class CopyTest {
        public static void main(String[] args) throws CloneNotSupportedException {
            Teacher2 teacher = new Teacher2();
            teacher.setName("Delacey");
            teacher.setAge(29);
    
            Student3 student1 = new Student3();
            student1.setName("Dream");
            student1.setAge(18);
            student1.setTeacher(teacher);
    
            Student3 student2 = (Student3) student1.clone();
            System.out.println("拷贝后");
            System.out.println(student2.getName());
            System.out.println(student2.getAge());
            System.out.println(student2.getTeacher().getName());
            System.out.println(student2.getTeacher().getAge());
    
            System.out.println("修改老师的信息后-------------");
            // 修改老师的信息
            teacher.setName("Jam");
            System.out.println(student1.getTeacher().getName());//Jam
            System.out.println(student2.getTeacher().getName());//Delacey
        }
    }
    

    利用序列化实现深拷贝

    package blog;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    public class DeepCopyServiable {
        public static void main(String[] args) throws Exception {
            Teacher3 t = new Teacher3();
            t.setName("Taylor");
            t.setAge(28);
    
            Student3 s1 = new Student3();
            s1.setAge(20);
            s1.setName("blank space");
            s1.setTeacher(t);
    
            Student3 s2 = (Student3) s1.deepClone();
    
            System.out.println("拷贝后:");
            System.out.println(s2.getName());
            System.out.println(s2.getAge());
            System.out.println(s2.getTeacher().getName());
            System.out.println(s2.getTeacher().getAge());
            System.out.println("---------------------------");
    
            t.setName("swift");
    
            System.out.println("修改后:");
            System.out.println(s1.getTeacher().getName());
            System.out.println(s2.getTeacher().getName());
        }
    
    }
    
    class Teacher3 implements Serializable
    {
        private String name;
        private int age;
    
        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;
        }
    
    }
    
    class Student3 implements Serializable
    {
        private String name;
        private int age;
        private Teacher3 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 Teacher3 getTeacher()
        {
            return teacher;
        }
    
        public void setTeacher(Teacher3 teacher)
        {
            this.teacher = teacher;
        }
    
        public Object deepClone() throws Exception
        {
            // 序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
    
            oos.writeObject(this);
    
            // 反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
    
            return ois.readObject();
        }
    
    }

    重写clone方法 与 通过序列化 两种拷贝方式比较:

    clone方法:

    优点:速度快,效率高

    缺点:在对象引用比较深时,使用此方式比较繁琐

    通过序列化:

    优点:非常简便的就可以完成深度copy

    缺点:由于序列化的过程需要跟磁盘打交道,因此效率会低于clone方式

    在java语言中,使用new创建对象与使用clone方法复制一个对象有什么不同?

    用new创建对象本意是分配内存。程序到new操作符时,首先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这就叫对象的初始化。对象初始化完毕后,可以把引用发布到外部,在外部就可以使用这个引用操纵这个对象。

    clone在第一步和new相似,都是分配内存的,调用clone方法时,分配的内存和源对象相同,然后在使用原对象中对应的各个域,填充新对象的域,填充完成之后,clone方法返回,一个新的相同对象就能被创建,同样这个新对象的引用发布到外部。

  • 相关阅读:
    [多线程]使用信号量进行同步
    [多线程]互斥锁与信号量的区别
    [多线程]环形缓冲区以及多线程条件同步
    [多线程]LINUX c多线程编程-线程初始化与建立
    [STL]bitset使用
    [算法]败者树
    【Rollo的Python之路】Python:字符串内置函数
    【Rollo的Python之路】Python:字典的学习笔记
    【Rollo的Python之路】 购物车程序练习
    【Rollo的Python之路】Python 元组的学习
  • 原文地址:https://www.cnblogs.com/mergy/p/12666511.html
Copyright © 2011-2022 走看看