浅拷贝和深拷贝的方法java_jdg粗中有细

浅拷贝和深拷贝的方法java_jdg粗中有细1.拷贝的引入(1)引用拷贝创建一个指向对象的引用变量的拷贝。例1:Teacherteacher=newTeacher(“Taylor”,26);Teacherotherteacher=teacher;System.out.println(teacher);System.out.println(otherteacher);输出结果:blog.Teacher@355da254bl

1.拷贝的引入

(1)引用拷贝

创建一个指向对象的引用变量的拷贝。

例1:

Teacher teacher = new Teacher("Taylor",26);
Teacher otherteacher = teacher;
System.out.println(teacher);
System.out.println(otherteacher);

输出结果:

blog.Teacher@355da254
blog.Teacher@355da254

结果分析:由输出结果可以看出,它们的地址值是相同的,那么它们肯定是同一个对象。teacher和otherteacher的只是引用而已,他们都指向了一个相同的对象Teacher(“Taylor”,26)。 这就叫做引用拷贝。

例1 图解:
这里写图片描述

(2)对象拷贝

创建对象本身的一个副本。

例2:

Teacher teacher = new Teacher("Swift",26);
Teacher otherteacher = (Teacher)teacher.clone();
System.out.println(teacher);
System.out.println(otherteacher);

输出结果:

blog.Teacher@355da254
blog.Teacher@4dc63996

结果分析:由输出结果可以看出,它们的地址是不同的,也就是说创建了新的对象, 而不是把原对象的地址赋给了一个新的引用变量,这就叫做对象拷贝。

例2 图解:
这里写图片描述

注:深拷贝和浅拷贝都是对象拷贝

2.浅拷贝

(1)定义:

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。

简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象

(2)浅拷贝实例:

例3:

public class ShallowCopy { 
   
    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());
        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());
        System.out.println(student2.getTeacher().getName());
    }

}

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 { 
   
        Object object = super.clone();
        return object;
    }

}

输出结果:

拷贝后
Dream
18
Delacey
29
修改老师的信息后-------------
Jam
Jam

结果分析: 两个引用student1和student2指向不同的两个对象,但是两个引用student1和student2中的两个teacher引用指向的是同一个对象,所以说明是浅拷贝。

例3 图解:
这里写图片描述

3.深拷贝

(1)定义:

深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

(2)实现深拷贝(实例1):

例4:

public class DeepCopy { 
   
    public static void main(String[] args) throws Exception { 
   
        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());
        System.out.println(student2.getTeacher().getName());
    }
}

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 { 
   
        // 浅复制时:
        // Object object = super.clone();
        // return object;

        // 改为深复制:
        Student3 student = (Student3) super.clone();
        // 本来是浅复制,现在将Teacher对象复制一份并重新set进来
        student.setTeacher((Teacher2) student.getTeacher().clone());
        return student;
    }

}

输出结果:

拷贝后
Dream
18
Delacey
29
修改老师的信息后-------------
Jam
Delacey

结果分析:
两个引用student1和student2指向不同的两个对象,两个引用student1和student2中的两个teacher引用指向的是两个对象,但对teacher对象的修改只能影响student1对象,所以说是深拷贝。

例4 图解1(teacher姓名Delacey更改前):

这里写图片描述

例4 图解2(teacher姓名Jam更改后):

这里写图片描述

(3)利用序列化实现深拷贝(实例2)

例5:

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();
    }
}

输出结果:

拷贝后:
blank space
20
Taylor
28
---------------------------
修改后:
swift
Taylor

结果分析:说明用序列化的方式实现了对象的深拷贝

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/234284.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Python怎么输入小数和整数_python输入非负整数

    Python怎么输入小数和整数_python输入非负整数python匹配整数或者小数(包括正数和负数)(简单易懂,代码可以直接运行)*这个实验算是五个正则表达式里面最难的的哪一个了,?是正则表达式里面贪婪与非贪婪的概念,有?则-?可有可无,刚好可以用于判断正数和负数,.在正则表达式里面表示的是任意字符(空格除外),因此如果要想表示小数点,需要加上以恶搞转义字符\,而区分整数和小数这两种情况,则需要加上一个|符号,表示前面的字符出现0次一次,+表示前面的字符出现1次以上#匹配整数或者小数num=’3333.3333’sss=re.search(r

    2022年9月1日
  • pytest报错_git代码提交流程

    pytest报错_git代码提交流程前言我们每天写完自动化用例后都会提交到git仓库,随着用例的增多,为了保证仓库代码的干净,当有用例新增的时候,我们希望只运行新增的未提交git仓库的用例。pytest-picked插件可以

    2022年7月30日
  • Nginx负载均衡策略_nginx高可用集群和负载均衡集群

    Nginx负载均衡策略_nginx高可用集群和负载均衡集群nginx的负载均衡策略有4种:轮询(默认)最基本的配置方法,它是upstream的默认策略,每个请求会按时间顺序逐一分配到不同的后端服务器。参数有:项目Valuefail_timeout与max_fails结合使用max_fails设置在fail_timeout参数设置的时间内最大失败次数,如果在这个时间内,所有针对该服务器的请求都失败了,那么认为该服务器会被认为是停机了fail_time服务器会被认为停机的时间长度,默认为10s。backup标记该服

    2022年10月13日
  • 弗曼技巧笔记

    弗曼技巧笔记弗曼技巧学习过程:选择一个概念 向其他人讲解这个概念 对讲解中出现的卡壳发现不懂的问题,回头去进一步学习学习过程中使用流程图,便于理解与记忆。弗曼技巧注重于正负反馈,有了正负反馈才能够对知识进行更好的理解。不同方式下学习内容留存率:弗曼技巧使用了最有效的方式—教授给他人。讲解的方式:可以依靠简化或类比的方式进行讲解,直到对方理解。…

    2022年6月14日
  • 优麒麟 2204 安装 Fcitx5 输入法

    优麒麟 2204 安装 Fcitx5 输入法Fcitx5是继Fcitx之后的新一代输入法框架,优麒麟2204默认安装的是Fcitx,而Fcitx和Fcitx5是相互冲突的,因此安装Fcitx5之前需要先卸载Fcitx。

    2022年7月14日
  • java string转long类型(c语言字符串存入数组)

    背景在日常开发需求中,跟前端交互,时有传由多个id组成的id字符串给后端的情况,然而在数据库中保存的id是整型,比如Long类型,这个时候就需要把字符串数组转成一个Long类型的List了代码publicstaticvoidmain(String[]args){str…

    2022年4月15日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号