千家信息网

Java中浅拷贝和深拷贝该怎么理解

发表于:2025-01-21 作者:千家信息网编辑
千家信息网最后更新 2025年01月21日,这篇文章给大家介绍Java中浅拷贝和深拷贝该怎么理解,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java浅拷贝深拷贝浅拷贝和深拷贝涉及到了Object类中的clone()方法实
千家信息网最后更新 2025年01月21日Java中浅拷贝和深拷贝该怎么理解

这篇文章给大家介绍Java中浅拷贝和深拷贝该怎么理解,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

Java浅拷贝深拷贝

浅拷贝和深拷贝涉及到了Object类中的clone()方法

实现浅拷贝

浅拷贝的实现需要类重写clone()方法

浅拷贝会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝

如果属性是基本类型,拷贝的就是基本类型的值;

如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象,导致两个对象的引用不等

实现浅拷贝很简单只需要将类实现Cloneable接口然后重写clone方法即可

class Person implements Cloneable {    String name;    int age;    public Person() {    }    public Person(String name, int age) {        this.name = name;        this.age = 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;    }    /**         * 重写clone()方法         *         * @return         * @throws CloneNotSupportedException         */    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    @Override    public String toString() {        return "Person{" +            "name='" + name + '\'' +            ", age=" + age +            '}';    }}

测试浅拷贝特性

public void testClone() throws CloneNotSupportedException {    Person person1 = new Person();    person1.setName("ccy");    person1.setAge(20);    Person person2 = (Person) person1.clone();    //查看浅拷贝效果    System.out.println(person1);    System.out.println(person2);    System.out.println(person1.getName() == person2.getName());    //验证clone()的特性    System.out.println(person1.clone() != person1);    System.out.println(person1.clone().getClass() == person1.getClass());    //如果是基本类型浅拷贝直接赋值值,如果是引用类型浅拷贝指向其内存地址即共享内存地址    //改变person1的引用类型String属性的值,引用发生改变    person1.setName("zfs");    System.out.println(person2.getName());}

实现深拷贝

对于上述的问题虽然拷贝的两个对象不同,但其内部的一些引用还是相同的,怎么样绝对的拷贝这个对象,使这个对象完全独立于原对象呢?就使用我们的深拷贝了。深拷贝:在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量。

在具体实现深拷贝上,这里提供两个方式,重写clone()方法和序列法。

重写clone()方法

如果使用重写clone()方法实现深拷贝,那么要将类中所有自定义引用变量的类也去实现Cloneable接口实现clone()方法。对于字符类可以创建一个新的字符串实现拷贝。但是对于自定义类需要实现cloneable重写clone,这样做就太麻烦了所以我们使用序列化

序列化

序列化后将二进制字节流内容写到一个媒介(文本或字节数组),然后是从这个媒介读取数据,原对象写入这个媒介后拷贝给clone对象,原对象的修改不会影响clone对象,因为clone对象是从这个媒介读取。

熟悉对象缓存的知道我们经常将Java对象缓存到Redis中,然后还可能从Redis中读取生成Java对象,这就用到序列化和反序列化。一般可以将Java对象存储为字节流或者json串然后反序列化成Java对象。因为序列化会储存对象的属性但是不会也无法存储对象在内存中地址相关信息。所以在反序列化成Java对象时候会重新创建所有的引用对象。

在具体实现上,自定义的类需要实现Serializable接口

class Person implements Serializable {    String name;    int age;    public Person() {    }    public Person(String name, int age) {        this.name = name;        this.age = 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 String toString() {        return "Person{" +            "name='" + name + '\'' +            ", age=" + age +            '}';    }    protected Person 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 (Person) ois.readObject();    }}

测试方法

public void testClone() throws Exception {    Person person1 = new Person();    person1.setName("ccy");    person1.setAge(20);    Person person2 = person1.deepClone();    System.out.println(person1.getName() == person2.getName());}

可以看到两个引用对象的地址并不同,成功实现了深拷贝

关于Java中浅拷贝和深拷贝该怎么理解就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

拷贝 对象 序列 方法 地址 类型 内存 属性 两个 媒介 内容 接口 不同 变量 字符 就是 数据 时候 更多 特性 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 哈利波特同一个服务器怎么开小号 一台服务器能做两种raid吗 潍柴动力电控软件开发 数据库锁表跟踪分析 共筑网络安全守护绿色家园图片 国际货币基金组织数据库技术类 骑马与砍杀总被服务器踢出 网络安全手抄报关于黑客 服务器设计主要是做什么 医院网络安全发展趋势 湖北智能软件开发案例 杭州泉格网络技术有限公司 day服务器进不去 网络安全师傅带徒弟计划 中油龙慧软件开发应届生工资 浙江新一代网络技术服务咨询报价 数据库正常运行是什么样 哪里能找到软件开发的客户 怎么区分数据库系统 公路工程安全风险数据库 西藏智慧人口管理软件开发 计算机网络安全知识付费 布卡服务器 网络安全如何评估 山西pdu服务器电源哪家强 饥荒服务器搭建证书不存在 软件开发制定质量标准 暴雪软件开发招聘 网络安全应急解决方案 io模块与串口服务器区别
0